diff options
Diffstat (limited to 'protocols/Telegram/tdlib/td/test/message_entities.cpp')
-rw-r--r-- | protocols/Telegram/tdlib/td/test/message_entities.cpp | 269 |
1 files changed, 198 insertions, 71 deletions
diff --git a/protocols/Telegram/tdlib/td/test/message_entities.cpp b/protocols/Telegram/tdlib/td/test/message_entities.cpp index 378e76b23a..64cd7dcca9 100644 --- a/protocols/Telegram/tdlib/td/test/message_entities.cpp +++ b/protocols/Telegram/tdlib/td/test/message_entities.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -29,7 +29,7 @@ static void check_mention(const td::string &str, const td::vector<td::string> &e result.push_back(it.str()); } if (result != expected) { - LOG(FATAL) << td::tag("text", str) << td::tag("got", td::format::as_array(result)) + LOG(FATAL) << td::tag("text", str) << td::tag("receive", td::format::as_array(result)) << td::tag("expected", td::format::as_array(expected)); } } @@ -60,7 +60,7 @@ static void check_bot_command(const td::string &str, const td::vector<td::string result.push_back(it.str()); } if (result != expected) { - LOG(FATAL) << td::tag("text", str) << td::tag("got", td::format::as_array(result)) + LOG(FATAL) << td::tag("text", str) << td::tag("receive", td::format::as_array(result)) << td::tag("expected", td::format::as_array(expected)); } } @@ -84,7 +84,7 @@ static void check_hashtag(const td::string &str, const td::vector<td::string> &e result.push_back(it.str()); } if (result != expected) { - LOG(FATAL) << td::tag("text", str) << td::tag("got", td::format::as_array(result)) + LOG(FATAL) << td::tag("text", str) << td::tag("receive", td::format::as_array(result)) << td::tag("expected", td::format::as_array(expected)); } } @@ -128,7 +128,7 @@ static void check_cashtag(const td::string &str, const td::vector<td::string> &e result.push_back(it.str()); } if (result != expected) { - LOG(FATAL) << td::tag("text", str) << td::tag("got", td::format::as_array(result)) + LOG(FATAL) << td::tag("text", str) << td::tag("receive", td::format::as_array(result)) << td::tag("expected", td::format::as_array(expected)); } } @@ -190,7 +190,7 @@ static void check_media_timestamp(const td::string &str, const td::vector<std::p auto result = td::transform(td::find_media_timestamps(str), [](auto &&entity) { return std::make_pair(entity.first.str(), entity.second); }); if (result != expected) { - LOG(FATAL) << td::tag("text", str) << td::tag("got", td::format::as_array(result)) + LOG(FATAL) << td::tag("text", str) << td::tag("receive", td::format::as_array(result)) << td::tag("expected", td::format::as_array(expected)); } } @@ -235,7 +235,7 @@ static void check_bank_card_number(const td::string &str, const td::vector<td::s result.push_back(it.str()); } if (result != expected) { - LOG(FATAL) << td::tag("text", str) << td::tag("got", td::format::as_array(result)) + LOG(FATAL) << td::tag("text", str) << td::tag("receive", td::format::as_array(result)) << td::tag("expected", td::format::as_array(expected)); } } @@ -284,7 +284,7 @@ static void check_tg_url(const td::string &str, const td::vector<td::string> &ex result.push_back(it.str()); } if (result != expected) { - LOG(FATAL) << td::tag("text", str) << td::tag("got", td::format::as_array(result)) + LOG(FATAL) << td::tag("text", str) << td::tag("receive", td::format::as_array(result)) << td::tag("expected", td::format::as_array(expected)); } } @@ -464,11 +464,11 @@ static void check_url(const td::string &str, const td::vector<td::string> &expec } } if (result_urls != expected_urls) { - LOG(FATAL) << td::tag("text", str) << td::tag("got", td::format::as_array(result_urls)) + LOG(FATAL) << td::tag("text", str) << td::tag("receive", td::format::as_array(result_urls)) << td::tag("expected", td::format::as_array(expected_urls)); } if (result_email_addresses != expected_email_addresses) { - LOG(FATAL) << td::tag("text", str) << td::tag("got", td::format::as_array(result_email_addresses)) + LOG(FATAL) << td::tag("text", str) << td::tag("receive", td::format::as_array(result_email_addresses)) << td::tag("expected", td::format::as_array(expected_email_addresses)); } } @@ -501,6 +501,10 @@ TEST(MessageEntities, url) { check_url("ftp://telegram.org", {"ftp://telegram.org"}); check_url("ftps://telegram.org", {}); check_url("sftp://telegram.org", {}); + check_url("tonsite://telegram.ton", {"tonsite://telegram.ton"}); + check_url("telegram.ton", {"telegram.ton"}); + check_url("telegram.onion", {"telegram.onion"}); + check_url("telegram.tonsite", {}); check_url("hTtPs://telegram.org", {"hTtPs://telegram.org"}); check_url("HTTP://telegram.org", {"HTTP://telegram.org"}); check_url("аHTTP://telegram.org", {"HTTP://telegram.org"}); @@ -787,17 +791,13 @@ TEST(MessageEntities, fix_formatted_text) { entities.emplace_back(td::MessageEntity::Type::Bold, 0, i); td::vector<td::MessageEntity> fixed_entities; - if (i != 33) { - fixed_entities.emplace_back(td::MessageEntity::Type::Bold, 32, i - 33); - } + fixed_entities.emplace_back(td::MessageEntity::Type::Bold, 0, i - 1 /* deleted \r */); check_fix_formatted_text(str, entities, fixed_str, fixed_entities, true, false, false, true); - td::string expected_str; + td::string expected_str = fixed_str.substr(0, 33); if (i != 33) { - fixed_entities.back().offset = 0; - fixed_entities.back().length = 1; + fixed_entities.back().length = 33; } - expected_str = "a"; check_fix_formatted_text(str, entities, expected_str, fixed_entities, false, false, false, false); } @@ -809,8 +809,13 @@ TEST(MessageEntities, fix_formatted_text) { check_fix_formatted_text(str, entities, true, true, true, true); check_fix_formatted_text(str, entities, false, false, false, false); } else { - check_fix_formatted_text(str, entities, str, {}, true, true, true, true); - check_fix_formatted_text(str, entities, str.substr(0, str.size() - 2), {}, false, false, false, false); + check_fix_formatted_text(str, entities, str, {{td::MessageEntity::Type::Bold, i, 1}}, true, true, true, true); + if (i == 2) { + check_fix_formatted_text(str, entities, str.substr(0, str.size() - 2), {{td::MessageEntity::Type::Bold, i, 1}}, + false, false, false, false); + } else { + check_fix_formatted_text(str, entities, str.substr(0, str.size() - 2), {}, false, false, false, false); + } } } @@ -850,18 +855,9 @@ TEST(MessageEntities, fix_formatted_text) { fixed_str = skip_trim ? "aba \n caba " : "aba \n caba"; auto fixed_length = offset <= 4 && offset + length >= 5 ? length - 1 : length; auto fixed_offset = offset >= 5 ? offset - 1 : offset; - if (static_cast<size_t>(fixed_offset) >= fixed_str.size()) { - fixed_length = 0; - } while (static_cast<size_t>(fixed_offset + fixed_length) > fixed_str.size()) { fixed_length--; } - if (type == td::MessageEntity::Type::Bold || type == td::MessageEntity::Type::Url) { - while (fixed_length > 0 && (fixed_str[fixed_offset] == ' ' || fixed_str[fixed_offset] == '\n')) { - fixed_offset++; - fixed_length--; - } - } td::vector<td::MessageEntity> entities; entities.emplace_back(type, offset, length); @@ -872,17 +868,11 @@ TEST(MessageEntities, fix_formatted_text) { } td::vector<td::MessageEntity> fixed_entities; if (fixed_length > 0) { - for (auto i = 0; i < length; i++) { - if (!td::is_space(str[offset + i]) || type == td::MessageEntity::Type::TextUrl || - type == td::MessageEntity::Type::MentionName) { - fixed_entities.emplace_back(type, fixed_offset, fixed_length); - if (type == td::MessageEntity::Type::TextUrl) { - fixed_entities.back().argument = "t.me"; - } else if (type == td::MessageEntity::Type::MentionName) { - fixed_entities.back().user_id = user_id; - } - break; - } + fixed_entities.emplace_back(type, fixed_offset, fixed_length); + if (type == td::MessageEntity::Type::TextUrl) { + fixed_entities.back().argument = "t.me"; + } else if (type == td::MessageEntity::Type::MentionName) { + fixed_entities.back().user_id = user_id; } } check_fix_formatted_text(str, entities, fixed_str, fixed_entities, true, false, false, skip_trim); @@ -904,13 +894,7 @@ TEST(MessageEntities, fix_formatted_text) { td::vector<td::MessageEntity> fixed_entities; if (length > 0) { - if (offset == 3) { - if (length >= 2) { - fixed_entities.emplace_back(td::MessageEntity::Type::Bold, offset + 1, length - 1); - } - } else { - fixed_entities.emplace_back(td::MessageEntity::Type::Bold, offset, length); - } + fixed_entities.emplace_back(td::MessageEntity::Type::Bold, offset, length); } check_fix_formatted_text(str, entities, str, fixed_entities, true, false, false, false); @@ -958,6 +942,9 @@ TEST(MessageEntities, fix_formatted_text) { if (i < 4) { fixed_entities.emplace_back(td::MessageEntity::Type::Bold, i * 3, 2); } + if (i < 3) { + fixed_entities.emplace_back(td::MessageEntity::Type::Italic, i * 3 + 2, 1); + } } check_fix_formatted_text(str, entities, td::utf8_utf16_substr(str, 3, 11).str(), fixed_entities, false, false, @@ -974,10 +961,10 @@ TEST(MessageEntities, fix_formatted_text) { check_fix_formatted_text("a \r", {{td::MessageEntity::Type::Bold, 0, 3}, {td::MessageEntity::Type::Underline, 2, 1}}, "a ", {{td::MessageEntity::Type::Bold, 0, 2}}, true, false, false, true); check_fix_formatted_text("a \r ", {{td::MessageEntity::Type::Bold, 0, 4}, {td::MessageEntity::Type::Underline, 2, 1}}, - "a ", {{td::MessageEntity::Type::Bold, 0, 2}}, true, false, false, true); - check_fix_formatted_text( - "a \r b", {{td::MessageEntity::Type::Bold, 0, 5}, {td::MessageEntity::Type::Underline, 2, 1}}, "a b", - {{td::MessageEntity::Type::Bold, 0, 2}, {td::MessageEntity::Type::Bold, 3, 1}}, true, false, false, true); + "a ", {{td::MessageEntity::Type::Bold, 0, 3}}, true, false, false, true); + check_fix_formatted_text("a \r b", + {{td::MessageEntity::Type::Bold, 0, 5}, {td::MessageEntity::Type::Underline, 2, 1}}, "a b", + {{td::MessageEntity::Type::Bold, 0, 4}}, true, false, false, true); check_fix_formatted_text("a\rbc\r", {{td::MessageEntity::Type::Italic, 0, 1}, @@ -1014,6 +1001,7 @@ TEST(MessageEntities, fix_formatted_text) { check_fix_formatted_text("@tests @tests", {{td::MessageEntity::Type::Italic, 0, 13}}, "@tests @tests", {{td::MessageEntity::Type::Mention, 0, 6}, {td::MessageEntity::Type::Italic, 0, 6}, + {td::MessageEntity::Type::Italic, 6, 1}, {td::MessageEntity::Type::Mention, 7, 6}, {td::MessageEntity::Type::Italic, 7, 6}}); @@ -1113,7 +1101,7 @@ TEST(MessageEntities, fix_formatted_text) { check_fix_formatted_text("example.com a", {{td::MessageEntity::Type::Italic, 0, 13}}, "example.com a", {{td::MessageEntity::Type::Url, 0, 11}, {td::MessageEntity::Type::Italic, 0, 11}, - {td::MessageEntity::Type::Italic, 12, 1}}); + {td::MessageEntity::Type::Italic, 11, 2}}); check_fix_formatted_text("a example.com", {{td::MessageEntity::Type::Italic, 0, 13}}, "a example.com", {{td::MessageEntity::Type::Italic, 0, 2}, {td::MessageEntity::Type::Url, 2, 11}, @@ -1134,7 +1122,7 @@ TEST(MessageEntities, fix_formatted_text) { auto n = td::Random::fast(1, 20); td::vector<td::MessageEntity> entities; for (int j = 0; j < n; j++) { - td::int32 type = td::Random::fast(4, 16); + td::int32 type = td::Random::fast(4, static_cast<int>(td::MessageEntity::Type::Size) - 1); td::int32 offset = td::Random::fast(0, static_cast<int>(str.size()) - 1); auto max_length = static_cast<int>(str.size() - offset); if ((test_n & 1) != 0 && max_length > 4) { @@ -1156,7 +1144,7 @@ TEST(MessageEntities, fix_formatted_text) { auto old_type_mask = get_type_mask(str.size(), entities); ASSERT_TRUE(td::fix_formatted_text(str, entities, false, false, true, true, false).is_ok()); auto new_type_mask = get_type_mask(str.size(), entities); - auto splittable_mask = (1 << 5) | (1 << 6) | (1 << 14) | (1 << 15); + auto splittable_mask = (1 << 5) | (1 << 6) | (1 << 14) | (1 << 15) | (1 << 19); auto pre_mask = (1 << 7) | (1 << 8) | (1 << 9); for (std::size_t pos = 0; pos < str.size(); pos++) { if ((new_type_mask[pos] & pre_mask) != 0) { @@ -1176,7 +1164,9 @@ TEST(MessageEntities, fix_formatted_text) { if (keep_url && ((1 << static_cast<td::int32>(entity.type)) & splittable_mask) == 0 && !(end <= url_offset || url_end <= offset)) { - keep_url = (entity.type == td::MessageEntity::Type::BlockQuote && offset <= url_offset && url_end <= end); + keep_url = ((entity.type == td::MessageEntity::Type::BlockQuote || + entity.type == td::MessageEntity::Type::ExpandableBlockQuote) && + offset <= url_offset && url_end <= end); } } ASSERT_EQ(keep_url, std::count(entities.begin(), entities.end(), url_entity) == 1); @@ -1199,7 +1189,8 @@ TEST(MessageEntities, fix_formatted_text) { // pre can't contain other entities ASSERT_TRUE((type_mask & pre_mask) == 0); - if ((type_mask & splittable_mask) == 0 && entities[i].type != td::MessageEntity::Type::BlockQuote) { + if ((type_mask & splittable_mask) == 0 && entities[i].type != td::MessageEntity::Type::BlockQuote && + entities[i].type != td::MessageEntity::Type::ExpandableBlockQuote) { // continuous entities can contain only splittable entities ASSERT_TRUE(((1 << static_cast<td::int32>(entities[j].type)) & splittable_mask) != 0); } @@ -1217,6 +1208,24 @@ TEST(MessageEntities, fix_formatted_text) { {}); } +TEST(MessageEntities, is_visible_url) { + td::string str = "a telegram.org telegran.org telegrao.org telegram.orc telegrap.org c"; + td::vector<td::MessageEntity> entities; + entities.emplace_back(td::MessageEntity::Type::TextUrl, 0, 1, "telegrab.org"); + entities.emplace_back(td::MessageEntity::Type::TextUrl, static_cast<td::int32>(str.size()) - 1, 1, "telegrax.org"); + td::fix_formatted_text(str, entities, false, false, false, false, true).ensure(); + td::FormattedText text{std::move(str), std::move(entities)}; + ASSERT_EQ(td::get_first_url(text), "telegrab.org"); + ASSERT_TRUE(!td::is_visible_url(text, "telegrab.org")); + ASSERT_TRUE(td::is_visible_url(text, "telegram.org")); + ASSERT_TRUE(td::is_visible_url(text, "telegran.org")); + ASSERT_TRUE(td::is_visible_url(text, "telegrao.org")); + ASSERT_TRUE(!td::is_visible_url(text, "telegram.orc")); + ASSERT_TRUE(td::is_visible_url(text, "telegrap.org")); + ASSERT_TRUE(!td::is_visible_url(text, "telegraf.org")); + ASSERT_TRUE(!td::is_visible_url(text, "telegrax.org")); +} + static void check_parse_html(td::string text, const td::string &result, const td::vector<td::MessageEntity> &entities) { auto r_entities = td::parse_html(text); ASSERT_TRUE(r_entities.is_ok()); @@ -1241,8 +1250,7 @@ TEST(MessageEntities, parse_html) { check_parse_html("🏟 🏟<<abac aba>", "Unsupported start tag \"abac\" at byte offset 13"); check_parse_html("🏟 🏟<<abac>", "Unsupported start tag \"abac\" at byte offset 13"); check_parse_html("🏟 🏟<<i =aba>", "Empty attribute name in the tag \"i\" at byte offset 13"); - check_parse_html("🏟 🏟<<i aba>", - "Expected equal sign in declaration of an attribute of the tag \"i\" at byte offset 13"); + check_parse_html("🏟 🏟<<i aba>", "Can't find end tag corresponding to start tag \"i\""); check_parse_html("🏟 🏟<<i aba = ", "Unclosed start tag \"i\" at byte offset 13"); check_parse_html("🏟 🏟<<i aba = 190azAz-.,", "Unexpected end of name token at byte offset 27"); check_parse_html("🏟 🏟<<i aba = \"<>">", "Unclosed start tag at byte offset 13"); @@ -1265,6 +1273,7 @@ TEST(MessageEntities, parse_html) { check_parse_html("➡️ ➡️<s>➡️ ➡️</s>", "➡️ ➡️➡️ ➡️", {{td::MessageEntity::Type::Strikethrough, 5, 5}}); check_parse_html("➡️ ➡️<strike>➡️ ➡️</strike>", "➡️ ➡️➡️ ➡️", {{td::MessageEntity::Type::Strikethrough, 5, 5}}); check_parse_html("➡️ ➡️<del>➡️ ➡️</del>", "➡️ ➡️➡️ ➡️", {{td::MessageEntity::Type::Strikethrough, 5, 5}}); + check_parse_html("➡️ ➡️<blockquote>➡️ ➡️</blockquote>", "➡️ ➡️➡️ ➡️", {{td::MessageEntity::Type::BlockQuote, 5, 5}}); check_parse_html("➡️ ➡️<i>➡️ ➡️</i><b>➡️ ➡️</b>", "➡️ ➡️➡️ ➡️➡️ ➡️", {{td::MessageEntity::Type::Italic, 5, 5}, {td::MessageEntity::Type::Bold, 10, 5}}); check_parse_html("🏟 🏟<i>🏟 <🏟</i>", "🏟 🏟🏟 <🏟", {{td::MessageEntity::Type::Italic, 5, 6}}); @@ -1349,11 +1358,22 @@ TEST(MessageEntities, parse_html) { check_parse_html("🏟 🏟<b aba = caba><tg-emoji emoji-id=\"1\">🏟</tg-emoji>1</b>", "🏟 🏟🏟1", {{td::MessageEntity::Type::Bold, 5, 3}, {td::MessageEntity::Type::CustomEmoji, 5, 2, td::CustomEmojiId(static_cast<td::int64>(1))}}); + check_parse_html("<blockquote cite=\"\" askdlbas nasjdbaj nj12b3>a<<pre >b;</></>", "a<b;", + {{td::MessageEntity::Type::BlockQuote, 0, 4}, {td::MessageEntity::Type::Pre, 2, 2}}); + check_parse_html("<blockquote expandable>a<<pre >b;</></>", "a<b;", + {{td::MessageEntity::Type::ExpandableBlockQuote, 0, 4}, {td::MessageEntity::Type::Pre, 2, 2}}); + check_parse_html("<blockquote expandable asd>a<<pre >b;</></>", "a<b;", + {{td::MessageEntity::Type::ExpandableBlockQuote, 0, 4}, {td::MessageEntity::Type::Pre, 2, 2}}); + check_parse_html("<blockquote expandable=false>a<<pre >b;</></>", "a<b;", + {{td::MessageEntity::Type::ExpandableBlockQuote, 0, 4}, {td::MessageEntity::Type::Pre, 2, 2}}); } static void check_parse_markdown(td::string text, const td::string &result, const td::vector<td::MessageEntity> &entities) { auto r_entities = td::parse_markdown_v2(text); + if (r_entities.is_error()) { + LOG(ERROR) << r_entities.error(); + } ASSERT_TRUE(r_entities.is_ok()); ASSERT_EQ(entities, r_entities.ok()); ASSERT_STREQ(result, text); @@ -1368,7 +1388,7 @@ static void check_parse_markdown(td::string text, td::Slice error_message) { TEST(MessageEntities, parse_markdown) { td::Slice reserved_characters("]()>#+-=|{}.!"); - td::Slice begin_characters("_*[~`"); + td::Slice begin_characters("_*[~`>"); for (char c = 1; c < 126; c++) { if (begin_characters.find(c) != td::Slice::npos) { continue; @@ -1405,6 +1425,7 @@ TEST(MessageEntities, parse_markdown) { check_parse_markdown("🏟 🏟__", "Can't find end of Underline entity at byte offset 9"); check_parse_markdown("🏟 🏟||test\\|", "Can't find end of Spoiler entity at byte offset 9"); check_parse_markdown("🏟 🏟!", "Character '!' is reserved and must be escaped with the preceding '\\'"); + check_parse_markdown("🏟 🏟>", "Character '>' is reserved and must be escaped with the preceding '\\'"); check_parse_markdown("🏟 🏟![", "Can't find end of CustomEmoji entity at byte offset 9"); check_parse_markdown("🏟 🏟![👍", "Can't find end of CustomEmoji entity at byte offset 9"); check_parse_markdown("🏟 🏟![👍]", "Custom emoji entity must contain a tg://emoji URL"); @@ -1414,6 +1435,12 @@ TEST(MessageEntities, parse_markdown) { check_parse_markdown("🏟 🏟![👍](tg://emoji#test)", "Custom emoji URL must have an emoji identifier"); check_parse_markdown("🏟 🏟![👍](tg://emoji?test=1#&id=25)", "Custom emoji URL must have an emoji identifier"); check_parse_markdown("🏟 🏟![👍](tg://emoji?test=1231&id=025)", "Invalid custom emoji identifier specified"); + check_parse_markdown(">*b\n>ld \n>bo\nld*\nasd\ndef", "Can't find end of Bold entity at byte offset 1"); + check_parse_markdown(">\n*a*>2", "Character '>' is reserved and must be escaped with the preceding '\\'"); + check_parse_markdown(">asd\n>q||e||w||\n||asdad", "Can't find end of Spoiler entity at byte offset 16"); + check_parse_markdown(">asd\n>q||ew\n||asdad", "Can't find end of Spoiler entity at byte offset 7"); + check_parse_markdown(">asd\n>q||e||w__\n||asdad", "Can't find end of Underline entity at byte offset 13"); + check_parse_markdown(">asd\n>q||e||w||a\n||asdad", "Can't find end of Spoiler entity at byte offset 13"); check_parse_markdown("", "", {}); check_parse_markdown("\\\\", "\\", {}); @@ -1478,6 +1505,71 @@ TEST(MessageEntities, parse_markdown) { {{0, 12, td::UserId(static_cast<td::int64>(123456))}}); check_parse_markdown("🏟 🏟![👍](TG://EMoJI/?test=1231&id=25#id=32)a", "🏟 🏟👍a", {{td::MessageEntity::Type::CustomEmoji, 5, 2, td::CustomEmojiId(static_cast<td::int64>(25))}}); + check_parse_markdown("> \n> \n>", " \n \n", {{td::MessageEntity::Type::BlockQuote, 0, 4}}); + check_parse_markdown("> \\>\n \\> \n>", " >\n > \n", {{td::MessageEntity::Type::BlockQuote, 0, 3}}); + check_parse_markdown("abc\n> \n> \n>\ndef", "abc\n \n \n\ndef", {{td::MessageEntity::Type::BlockQuote, 4, 5}}); + check_parse_markdown(">", "", {}); + check_parse_markdown(">a", "a", {{td::MessageEntity::Type::BlockQuote, 0, 1}}); + check_parse_markdown("\r>a", "\ra", {{td::MessageEntity::Type::BlockQuote, 1, 1}}); + check_parse_markdown("\r\r>\r\ra\r\n\r", "\r\r\r\ra\r\n\r", {{td::MessageEntity::Type::BlockQuote, 2, 5}}); + check_parse_markdown( + ">*bold _italic bold ~italic bold strikethrough ||italic bold strikethrough spoiler||~ __underline italic " + "bold___ bold*", + "bold italic bold italic bold strikethrough italic bold strikethrough spoiler underline italic bold bold", + {{td::MessageEntity::Type::BlockQuote, 0, 103}, + {td::MessageEntity::Type::Bold, 0, 103}, + {td::MessageEntity::Type::Italic, 5, 93}, + {td::MessageEntity::Type::Strikethrough, 17, 59}, + {td::MessageEntity::Type::Spoiler, 43, 33}, + {td::MessageEntity::Type::Underline, 77, 21}}); + check_parse_markdown(">*b\n>ld \n>bo\n>ld*\nasd\ndef", "b\nld \nbo\nld\nasd\ndef", + {{td::MessageEntity::Type::BlockQuote, 0, 12}, {td::MessageEntity::Type::Bold, 0, 11}}); + check_parse_markdown("*a\n>b\n>ld \n>bo\n>ld\nasd*\ndef", "a\nb\nld \nbo\nld\nasd\ndef", + {{td::MessageEntity::Type::Bold, 0, 17}, {td::MessageEntity::Type::BlockQuote, 2, 12}}); + check_parse_markdown(">`b\n>ld \n>bo\nld`\n>asd\ndef", "b\n>ld \n>bo\nld\nasd\ndef", + {{td::MessageEntity::Type::BlockQuote, 0, 18}, {td::MessageEntity::Type::Code, 0, 13}}); + check_parse_markdown("`>b\n>ld \n>bo\nld`\n>asd\ndef", ">b\n>ld \n>bo\nld\nasd\ndef", + {{td::MessageEntity::Type::Code, 0, 14}, {td::MessageEntity::Type::BlockQuote, 15, 4}}); + check_parse_markdown(">1", "1", {{td::MessageEntity::Type::BlockQuote, 0, 1}}); + check_parse_markdown(">\n1", "\n1", {{td::MessageEntity::Type::BlockQuote, 0, 1}}); + check_parse_markdown(">\n\r>2", "\n\r2", + {{td::MessageEntity::Type::BlockQuote, 0, 1}, {td::MessageEntity::Type::BlockQuote, 2, 1}}); + check_parse_markdown(">\n**>2", "\n2", + {{td::MessageEntity::Type::BlockQuote, 0, 1}, {td::MessageEntity::Type::BlockQuote, 1, 1}}); + check_parse_markdown(">**\n>2", "\n2", {{td::MessageEntity::Type::BlockQuote, 0, 2}}); + // check_parse_markdown("*>abcd*", "abcd", + // {{td::MessageEntity::Type::BlockQuote, 0, 4}, {td::MessageEntity::Type::Bold, 0, 4}}); + check_parse_markdown(">*abcd*", "abcd", + {{td::MessageEntity::Type::BlockQuote, 0, 4}, {td::MessageEntity::Type::Bold, 0, 4}}); + // check_parse_markdown(">*abcd\n*", "abcd\n", + // {{td::MessageEntity::Type::BlockQuote, 0, 5}, {td::MessageEntity::Type::Bold, 0, 5}}); + check_parse_markdown(">*abcd*\n", "abcd\n", + {{td::MessageEntity::Type::BlockQuote, 0, 5}, {td::MessageEntity::Type::Bold, 0, 4}}); + check_parse_markdown("*>abcd\n*", "abcd\n", + {{td::MessageEntity::Type::BlockQuote, 0, 5}, {td::MessageEntity::Type::Bold, 0, 5}}); + check_parse_markdown("abc\n>def\n>def\n\r>ghi2\njkl", "abc\ndef\ndef\n\rghi2\njkl", + {{td::MessageEntity::Type::BlockQuote, 4, 8}, {td::MessageEntity::Type::BlockQuote, 13, 5}}); + check_parse_markdown( + ">asd\n>q||e||w||\nasdad", "asd\nqew\nasdad", + {{td::MessageEntity::Type::ExpandableBlockQuote, 0, 8}, {td::MessageEntity::Type::Spoiler, 5, 1}}); + check_parse_markdown(">asd\n>q||ew||\nasdad", "asd\nqew\nasdad", + {{td::MessageEntity::Type::BlockQuote, 0, 8}, {td::MessageEntity::Type::Spoiler, 5, 2}}); + check_parse_markdown( + ">asd\r\n>q||e||w||\r\nasdad", "asd\r\nqew\r\nasdad", + {{td::MessageEntity::Type::ExpandableBlockQuote, 0, 10}, {td::MessageEntity::Type::Spoiler, 6, 1}}); + check_parse_markdown(">asd\r\n>q||ew||\r\nasdad", "asd\r\nqew\r\nasdad", + {{td::MessageEntity::Type::BlockQuote, 0, 10}, {td::MessageEntity::Type::Spoiler, 6, 2}}); + check_parse_markdown( + ">asd\r\n>q||e||w||\r\n", "asd\r\nqew\r\n", + {{td::MessageEntity::Type::ExpandableBlockQuote, 0, 10}, {td::MessageEntity::Type::Spoiler, 6, 1}}); + check_parse_markdown(">asd\r\n>q||ew||\r\n", "asd\r\nqew\r\n", + {{td::MessageEntity::Type::BlockQuote, 0, 10}, {td::MessageEntity::Type::Spoiler, 6, 2}}); + check_parse_markdown( + ">asd\r\n>q||e||w||", "asd\r\nqew", + {{td::MessageEntity::Type::ExpandableBlockQuote, 0, 8}, {td::MessageEntity::Type::Spoiler, 6, 1}}); + check_parse_markdown(">asd\r\n>q||ew||", "asd\r\nqew", + {{td::MessageEntity::Type::BlockQuote, 0, 8}, {td::MessageEntity::Type::Spoiler, 6, 2}}); + check_parse_markdown(">||", "", {}); } static void check_parse_markdown_v3(td::string text, td::vector<td::MessageEntity> entities, @@ -1628,8 +1720,8 @@ TEST(MessageEntities, parse_markdown_v3) { check_parse_markdown_v3("__ __", " ", {{td::MessageEntity::Type::Italic, 0, 1}}); check_parse_markdown_v3("__\n__", "\n", {{td::MessageEntity::Type::Italic, 0, 1}}); - check_parse_markdown_v3("__ __a", " a", {}, true); - check_parse_markdown_v3("__\n__a", "\na", {}, true); + check_parse_markdown_v3("__ __a", " a", {{td::MessageEntity::Type::Italic, 0, 1}}, true); + check_parse_markdown_v3("__\n__a", "\na", {{td::MessageEntity::Type::Italic, 0, 1}}, true); check_parse_markdown_v3("**** __a__ **b** ~~c~~ ||d||", "**** a b c d", {{td::MessageEntity::Type::Italic, 5, 1}, {td::MessageEntity::Type::Bold, 7, 1}, @@ -1764,9 +1856,10 @@ TEST(MessageEntities, parse_markdown_v3) { check_parse_markdown_v3( "__italic__ ~~strikethrough~~ **bold** `code` ```pre``` __[italic__ text_url](telegram.org) __italic**bold " "italic__bold**__italic__ ~~strikethrough~~ **bold** `code` ```pre``` __[italic__ text_url](telegram.org) " - "__italic**bold italic__bold** ||spoiler||", + "__italic**bold italic__bold** ||spoiler|| ```pre\nprecode``` init", + {{td::MessageEntity::Type::Italic, 271, 4}}, "italic strikethrough bold code pre italic text_url italicbold italicbolditalic strikethrough bold code pre " - "italic text_url italicbold italicbold spoiler", + "italic text_url italicbold italicbold spoiler precode init", {{td::MessageEntity::Type::Italic, 0, 6}, {td::MessageEntity::Type::Strikethrough, 7, 13}, {td::MessageEntity::Type::Bold, 21, 4}, @@ -1785,14 +1878,31 @@ TEST(MessageEntities, parse_markdown_v3) { {td::MessageEntity::Type::Italic, 107, 6}, {td::MessageEntity::Type::Italic, 123, 17}, {td::MessageEntity::Type::Bold, 129, 15}, - {td::MessageEntity::Type::Spoiler, 145, 7}}); + {td::MessageEntity::Type::Spoiler, 145, 7}, + {td::MessageEntity::Type::PreCode, 153, 7, "pre"}, + {td::MessageEntity::Type::Italic, 161, 4}}); + check_parse_markdown_v3("```\nsome code\n```", "some code\n", {{td::MessageEntity::Type::Pre, 0, 10}}); + check_parse_markdown_v3("asd\n```\nsome code\n```cabab", "asd\nsome code\ncabab", + {{td::MessageEntity::Type::Pre, 4, 10}}); + check_parse_markdown_v3("asd\naba```\nsome code\n```cabab", "asd\nabasome code\ncabab", + {{td::MessageEntity::Type::Pre, 7, 10}}); + check_parse_markdown_v3("asd\naba```\nsome code\n```\ncabab", "asd\nabasome code\n\ncabab", + {{td::MessageEntity::Type::Pre, 7, 10}}); + check_parse_markdown_v3("asd\naba```a b\nsome code\n```\ncabab", "asd\nabaa b\nsome code\n\ncabab", + {{td::MessageEntity::Type::Pre, 7, 14}}); + check_parse_markdown_v3("asd\naba```a!@#$%^&*(b\nsome code\n```\ncabab", "asd\nabasome code\n\ncabab", + {{td::MessageEntity::Type::PreCode, 7, 10, "a!@#$%^&*(b"}}); + check_parse_markdown_v3("```aba\n```", "aba\n", {{td::MessageEntity::Type::Pre, 0, 4}}); + check_parse_markdown_v3("```\n```", "\n", {{td::MessageEntity::Type::Pre, 0, 1}}); + check_parse_markdown_v3("```\n```", {{td::MessageEntity::Type::BlockQuote, 0, 7}}, "\n", + {{td::MessageEntity::Type::BlockQuote, 0, 1}, {td::MessageEntity::Type::Pre, 0, 1}}); td::vector<td::string> parts{"a", " #test__a", "__", "**", "~~", "||", "[", "](t.me)", "`"}; td::vector<td::MessageEntity::Type> types{ td::MessageEntity::Type::Bold, td::MessageEntity::Type::Italic, td::MessageEntity::Type::Underline, td::MessageEntity::Type::Strikethrough, td::MessageEntity::Type::Spoiler, td::MessageEntity::Type::Code, td::MessageEntity::Type::Pre, td::MessageEntity::Type::PreCode, td::MessageEntity::Type::TextUrl, - td::MessageEntity::Type::MentionName, td::MessageEntity::Type::Cashtag}; + td::MessageEntity::Type::MentionName, td::MessageEntity::Type::Cashtag, td::MessageEntity::Type::BlockQuote}; for (size_t test_n = 0; test_n < 1000; test_n++) { td::string str; int part_n = td::Random::fast(1, 200); @@ -1836,7 +1946,7 @@ static void check_get_markdown_v3(const td::string &result_text, const td::vecto } TEST(MessageEntities, get_markdown_v3) { - check_get_markdown_v3("``` ```", {}, " ", {{td::MessageEntity::Type::Pre, 0, 1}}); + check_get_markdown_v3("```\n ```", {}, " ", {{td::MessageEntity::Type::Pre, 0, 1}}); check_get_markdown_v3("` `", {}, " ", {{td::MessageEntity::Type::Code, 0, 1}}); check_get_markdown_v3("`\n`", {}, "\n", {{td::MessageEntity::Type::Code, 0, 1}}); check_get_markdown_v3("ab", {{td::MessageEntity::Type::Code, 0, 1}, {td::MessageEntity::Type::Pre, 1, 1}}, "ab", @@ -1851,16 +1961,18 @@ TEST(MessageEntities, get_markdown_v3) { check_get_markdown_v3("** **", {}, " ", {{td::MessageEntity::Type::Bold, 0, 1}}); check_get_markdown_v3("~~ ~~", {}, " ", {{td::MessageEntity::Type::Strikethrough, 0, 1}}); check_get_markdown_v3("|| ||", {}, " ", {{td::MessageEntity::Type::Spoiler, 0, 1}}); - check_get_markdown_v3("__a__ **b** ~~c~~ ||d|| e", {{td::MessageEntity::Type::PreCode, 24, 1, "C++"}}, "a b c d e", + check_get_markdown_v3("__a__ **b** ~~c~~ ||d|| e", {{td::MessageEntity::Type::PreCode, 24, 1, " C++"}}, "a b c d e", {{td::MessageEntity::Type::Italic, 0, 1}, {td::MessageEntity::Type::Bold, 2, 1}, {td::MessageEntity::Type::Strikethrough, 4, 1}, {td::MessageEntity::Type::Spoiler, 6, 1}, - {td::MessageEntity::Type::PreCode, 8, 1, "C++"}}); - check_get_markdown_v3("`ab` ```cd``` ef", {{td::MessageEntity::Type::PreCode, 14, 2, "C++"}}, "ab cd ef", - {{td::MessageEntity::Type::Code, 0, 2}, - {td::MessageEntity::Type::Pre, 3, 2}, - {td::MessageEntity::Type::PreCode, 6, 2, "C++"}}); + {td::MessageEntity::Type::PreCode, 8, 1, " C++"}}); + check_get_markdown_v3("```cpp\ngh```\n`ab`\n```\ncd```\nef", {{td::MessageEntity::Type::PreCode, 28, 2, " C++"}}, + "gh\nab\ncd\nef", + {{td::MessageEntity::Type::PreCode, 0, 2, "cpp"}, + {td::MessageEntity::Type::Code, 3, 2}, + {td::MessageEntity::Type::Pre, 6, 2}, + {td::MessageEntity::Type::PreCode, 9, 2, " C++"}}); check_get_markdown_v3("__asd__[__ab__cd](http://t.me/)", {}, "asdabcd", {{td::MessageEntity::Type::Italic, 0, 3}, {td::MessageEntity::Type::TextUrl, 3, 4, "http://t.me/"}, @@ -1879,4 +1991,19 @@ TEST(MessageEntities, get_markdown_v3) { {{td::MessageEntity::Type::TextUrl, 0, 16, "http://example.com/"}, {td::MessageEntity::Type::Bold, 0, 16}, {td::MessageEntity::Type::Italic, 0, 16}}); + check_get_markdown_v3("```\nsome code\n```", {}, "some code\n", {{td::MessageEntity::Type::Pre, 0, 10}}); + check_get_markdown_v3("asd\n```\nsome code\n```cabab", {}, "asd\nsome code\ncabab", + {{td::MessageEntity::Type::Pre, 4, 10}}); + check_get_markdown_v3("asd\naba```\nsome code\n```cabab", {}, "asd\nabasome code\ncabab", + {{td::MessageEntity::Type::Pre, 7, 10}}); + check_get_markdown_v3("asd\naba```\nsome code\n```\ncabab", {}, "asd\nabasome code\n\ncabab", + {{td::MessageEntity::Type::Pre, 7, 10}}); + check_get_markdown_v3("asd\naba```\na b\nsome code\n```\ncabab", {}, "asd\nabaa b\nsome code\n\ncabab", + {{td::MessageEntity::Type::Pre, 7, 14}}); + check_get_markdown_v3("asd\n```\na b\nsome code\n```\ncabab", {}, "asd\na b\nsome code\n\ncabab", + {{td::MessageEntity::Type::Pre, 4, 14}}); + check_get_markdown_v3("asd\naba```a!@#$%^&*(b\nsome code\n```\ncabab", {}, "asd\nabasome code\n\ncabab", + {{td::MessageEntity::Type::PreCode, 7, 10, "a!@#$%^&*(b"}}); + check_get_markdown_v3("```\naba\n```", {}, "aba\n", {{td::MessageEntity::Type::Pre, 0, 4}}); + check_get_markdown_v3("```\n```", {}, "\n", {{td::MessageEntity::Type::Pre, 0, 1}}); } |