Merge commit '35a9a93fc9adfbced4d5f59baf0c72a2f807f28a'
Conflicts: td/telegram/Client.cpp td/telegram/StickersManager.cpp td/telegram/WebPagesManager.cpp
This commit is contained in:
commit
f423fc0d81
@ -97,8 +97,10 @@ if (EMSCRIPTEN)
|
||||
set(ZLIB_LIBRARIES)
|
||||
set(ZLIB_INCLUDE_DIR)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s ALLOW_MEMORY_GROWTH=1 -s MEMFS_APPEND_TO_TYPED_ARRAYS=1 -s USE_ZLIB=1 -s MODULARIZE=1 -s WEBSOCKET_URL=\"'wss:#'\" -s EXTRA_EXPORTED_RUNTIME_METHODS=\"['FS','cwrap']\" -lidbfs.js -lworkerfs.js")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s ALLOW_MEMORY_GROWTH=1 -s MEMFS_APPEND_TO_TYPED_ARRAYS=1 -s USE_ZLIB=1 -s MODULARIZE=1 -s WEBSOCKET_URL=\"'wss:#'\" -s EXTRA_EXPORTED_RUNTIME_METHODS=\"['FS','cwrap']\" -lidbfs.js -lworkerfs.js")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s ALLOW_MEMORY_GROWTH=1 -s MEMFS_APPEND_TO_TYPED_ARRAYS=1 -s USE_ZLIB=1 -s MODULARIZE=1 \
|
||||
-s EXPORT_NAME=\"'createTdwebModule'\" -s WEBSOCKET_URL=\"'wss:#'\" -s EXTRA_EXPORTED_RUNTIME_METHODS=\"['FS','cwrap']\" -lidbfs.js -lworkerfs.js")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s ALLOW_MEMORY_GROWTH=1 -s MEMFS_APPEND_TO_TYPED_ARRAYS=1 -s USE_ZLIB=1 -s \
|
||||
MODULARIZE=1 -s EXPORT_NAME=\"'createTdwebModule'\" -s WEBSOCKET_URL=\"'wss:#'\" -s EXTRA_EXPORTED_RUNTIME_METHODS=\"['FS','cwrap']\" -lidbfs.js -lworkerfs.js")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -s DEMANGLE_SUPPORT=1 -s ASSERTIONS=1")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -s DEMANGLE_SUPPORT=1 -s ASSERTIONS=1")
|
||||
|
||||
@ -111,6 +113,7 @@ if (EMSCRIPTEN)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s WASM=1")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s WASM=1")
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --post-js ${CMAKE_CURRENT_SOURCE_DIR}/post.js")
|
||||
endif()
|
||||
|
||||
if (NOT OPENSSL_FOUND)
|
||||
|
2138
example/web/tdweb/package-lock.json
generated
2138
example/web/tdweb/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -26,7 +26,7 @@
|
||||
"@babel/plugin-transform-runtime": "^7.4.3",
|
||||
"@babel/preset-env": "^7.4.3",
|
||||
"@typescript-eslint/eslint-plugin": "^1.7.0",
|
||||
"acorn": "^6.1.1",
|
||||
"acorn": "^6.4.1",
|
||||
"babel-eslint": "^10.0.1",
|
||||
"babel-loader": "^8.0.5",
|
||||
"clean-webpack-plugin": "^2.0.1",
|
||||
@ -43,8 +43,8 @@
|
||||
"lint-staged": "^8.1.5",
|
||||
"prettier": "^1.17.0",
|
||||
"typescript": "^3.4.5",
|
||||
"webpack": "4.28.2",
|
||||
"webpack-cli": "^3.3.1",
|
||||
"webpack": "^4.44.1",
|
||||
"webpack-cli": "^3.3.12",
|
||||
"worker-loader": "^2.0.0"
|
||||
},
|
||||
"husky": {
|
||||
|
@ -169,7 +169,7 @@ class TdClient {
|
||||
'receive from worker: ',
|
||||
JSON.parse(
|
||||
JSON.stringify(response, (key, value) => {
|
||||
if (key === 'arr') {
|
||||
if (key === 'arr' || key === 'data') {
|
||||
return undefined;
|
||||
}
|
||||
return value;
|
||||
@ -233,7 +233,12 @@ class TdClient {
|
||||
}
|
||||
for (const key in response) {
|
||||
const field = response[key];
|
||||
if (field && typeof field === 'object') {
|
||||
if (
|
||||
field &&
|
||||
typeof field === 'object' &&
|
||||
key !== 'data' &&
|
||||
key !== 'arr'
|
||||
) {
|
||||
response[key] = this.prepareResponse(field);
|
||||
}
|
||||
}
|
||||
@ -579,7 +584,7 @@ class FileManager {
|
||||
file_id: info.file.id,
|
||||
offset: offset
|
||||
});
|
||||
log.error(count, size);
|
||||
//log.error(count, size);
|
||||
if (!size) {
|
||||
size = count.count;
|
||||
} else if (size > count.count) {
|
||||
@ -593,7 +598,7 @@ class FileManager {
|
||||
});
|
||||
res.data = new Blob([res.data]);
|
||||
res.transaction_id = -2;
|
||||
log.error(res);
|
||||
//log.error(res);
|
||||
return res;
|
||||
} catch (e) {
|
||||
log.info('readFilePart failed', info, offset, size, e);
|
||||
|
@ -63,18 +63,19 @@ async function initLocalForage() {
|
||||
|
||||
async function loadTdlibWasm(onFS, wasmUrl) {
|
||||
console.log('loadTdlibWasm');
|
||||
const Module = await import('./prebuilt/release/td_wasm.js');
|
||||
log.info('got td_wasm.js');
|
||||
const td_module = await import('./prebuilt/release/td_wasm.js');
|
||||
const createTdwebModule = td_module.default;
|
||||
log.info('got td_wasm.js', td_module, createTdwebModule);
|
||||
let td_wasm = td_wasm_release;
|
||||
if (wasmUrl) {
|
||||
td_wasm = wasmUrl;
|
||||
}
|
||||
const module = Module.default({
|
||||
let module = createTdwebModule({
|
||||
onRuntimeInitialized: () => {
|
||||
log.info('runtime intialized');
|
||||
},
|
||||
instantiateWasm: (imports, successCallback) => {
|
||||
log.info('start instantiateWasm', td_wasm);
|
||||
log.info('start instantiateWasm', td_wasm, imports);
|
||||
const next = instance => {
|
||||
log.info('finish instantiateWasm');
|
||||
successCallback(instance);
|
||||
@ -84,25 +85,22 @@ async function loadTdlibWasm(onFS, wasmUrl) {
|
||||
},
|
||||
ENVIROMENT: 'WORKER'
|
||||
});
|
||||
onFS(module.FS); // hack
|
||||
log.info('Wait module');
|
||||
module = await module;
|
||||
log.info('Got module', module);
|
||||
onFS(module.FS);
|
||||
const TdModule = new Promise((resolve, reject) =>
|
||||
module.then(m => {
|
||||
delete m.then;
|
||||
resolve(m);
|
||||
})
|
||||
);
|
||||
|
||||
return TdModule;
|
||||
//onFS(module.FS);
|
||||
return module;
|
||||
}
|
||||
|
||||
async function loadTdlibAsmjs(onFS) {
|
||||
console.log('loadTdlibAsmjs');
|
||||
const Module = await import('./prebuilt/release/td_asmjs.js');
|
||||
console.log('got td_asm.js');
|
||||
const createTdwebModule = (await import('./prebuilt/release/td_asmjs.js'))
|
||||
.default;
|
||||
console.log('got td_asm.js', createTdwebModule);
|
||||
const fromFile = 'td_asmjs.js.mem';
|
||||
const toFile = td_asmjs_mem_release;
|
||||
const module = Module.default({
|
||||
let module = createTdwebModule({
|
||||
onRuntimeInitialized: () => {
|
||||
console.log('runtime intialized');
|
||||
},
|
||||
@ -114,15 +112,12 @@ async function loadTdlibAsmjs(onFS) {
|
||||
},
|
||||
ENVIROMENT: 'WORKER'
|
||||
});
|
||||
onFS(module.FS);
|
||||
const TdModule = new Promise((resolve, reject) =>
|
||||
module.then(m => {
|
||||
delete m.then;
|
||||
resolve(m);
|
||||
})
|
||||
);
|
||||
|
||||
return TdModule;
|
||||
onFS(module.FS); // hack
|
||||
log.info('Wait module');
|
||||
module = await module;
|
||||
log.info('Got module', module);
|
||||
//onFS(module.FS);
|
||||
return module;
|
||||
}
|
||||
|
||||
async function loadTdlib(mode, onFS, wasmUrl) {
|
||||
@ -620,7 +615,10 @@ class TdClient {
|
||||
log.info('got TdModule');
|
||||
this.td_functions = {
|
||||
td_create: this.TdModule.cwrap('td_emscripten_create', 'number', []),
|
||||
td_send: this.TdModule.cwrap('td_emscripten_send', null, ['number', 'string']),
|
||||
td_send: this.TdModule.cwrap('td_emscripten_send', null, [
|
||||
'number',
|
||||
'string'
|
||||
]),
|
||||
td_execute: this.TdModule.cwrap('td_emscripten_execute', 'string', [
|
||||
'string'
|
||||
]),
|
||||
@ -633,7 +631,11 @@ class TdClient {
|
||||
})
|
||||
);
|
||||
},
|
||||
td_get_timeout: this.TdModule.cwrap('td_emscripten_get_timeout', 'number', [])
|
||||
td_get_timeout: this.TdModule.cwrap(
|
||||
'td_emscripten_get_timeout',
|
||||
'number',
|
||||
[]
|
||||
)
|
||||
};
|
||||
//this.onFS(this.TdModule.FS);
|
||||
this.FS = this.TdModule.FS;
|
||||
|
@ -982,9 +982,10 @@ loginUrlInfoRequestConfirmation url:string domain:string bot_user_id:int32 reque
|
||||
//@description Contains information about a message thread
|
||||
//@chat_id Identifier of the chat to which the message thread belongs
|
||||
//@message_thread_id Message thread identifier, unique within the chat
|
||||
//@reply_info Contains information about the message thread
|
||||
//@messages The messages from which the thread starts. The messages are returned in a reverse chronological order (i.e., in order of decreasing message_id)
|
||||
//@draft_message A draft of a message in the message thread; may be null
|
||||
messageThreadInfo chat_id:int53 message_thread_id:int53 messages:vector<message> draft_message:draftMessage = MessageThreadInfo;
|
||||
messageThreadInfo chat_id:int53 message_thread_id:int53 reply_info:messageReplyInfo messages:vector<message> draft_message:draftMessage = MessageThreadInfo;
|
||||
|
||||
|
||||
//@class RichText @description Describes a text object inside an instant-view web page
|
||||
|
Binary file not shown.
@ -12,6 +12,7 @@
|
||||
|
||||
#include "td/utils/buffer.h"
|
||||
#include "td/utils/format.h"
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/Named.h"
|
||||
#include "td/utils/port/detail/PollableFd.h"
|
||||
#include "td/utils/ScopeGuard.h"
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "td/mtproto/PacketInfo.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/Status.h"
|
||||
#include "td/utils/StorerBase.h"
|
||||
|
@ -153,9 +153,10 @@ class ClientManager::Impl final {
|
||||
ConcurrentScheduler::emscripten_clear_main_timeout();
|
||||
}
|
||||
if (response.request_id == 0 && response.object != nullptr &&
|
||||
response.object->get_id() == td::td_api::updateAuthorizationState::ID &&
|
||||
static_cast<const td::td_api::updateAuthorizationState *>(response.object.get())
|
||||
->authorization_state_->get_id() == td::td_api::authorizationStateClosed::ID) {
|
||||
response.object->get_id() == td_api::updateAuthorizationState::ID &&
|
||||
static_cast<const td_api::updateAuthorizationState *>(response.object.get())->authorization_state_->get_id() ==
|
||||
td_api::authorizationStateClosed::ID) {
|
||||
auto guard = concurrent_scheduler_->get_main_guard();
|
||||
auto it = tds_.find(response.client_id);
|
||||
CHECK(it != tds_.end());
|
||||
it->second.reset();
|
||||
@ -239,7 +240,7 @@ class MultiTd : public Actor {
|
||||
CHECK(td.empty());
|
||||
|
||||
string name = "Td";
|
||||
auto context = std::make_shared<td::ActorContext>();
|
||||
auto context = std::make_shared<ActorContext>();
|
||||
auto old_context = set_context(context);
|
||||
auto old_tag = set_tag(to_string(td_id));
|
||||
td = create_actor<Td>("Td", std::move(callback), options_);
|
||||
@ -255,8 +256,8 @@ class MultiTd : public Actor {
|
||||
}
|
||||
|
||||
void close(int32 td_id) {
|
||||
size_t erased = tds_.erase(td_id);
|
||||
CHECK(erased > 0);
|
||||
size_t erased_count = tds_.erase(td_id);
|
||||
CHECK(erased_count > 0);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -283,11 +284,15 @@ class TdReceiver {
|
||||
bool is_updates_locked = false;
|
||||
if (include_responses) {
|
||||
is_responses_locked = receive_responses_lock_.exchange(true);
|
||||
CHECK(!is_responses_locked);
|
||||
if (is_responses_locked) {
|
||||
LOG(FATAL) << "Receive is called after Client destroy, or simultaneously from different threads";
|
||||
}
|
||||
}
|
||||
if (include_updates) {
|
||||
is_updates_locked = receive_updates_lock_.exchange(true);
|
||||
CHECK(!is_updates_locked);
|
||||
if (is_updates_locked) {
|
||||
LOG(FATAL) << "Receive is called after Client destroy, or simultaneously from different threads";
|
||||
}
|
||||
}
|
||||
auto response = receive_unlocked(timeout, include_responses, include_updates);
|
||||
if (include_updates) {
|
||||
@ -298,7 +303,8 @@ class TdReceiver {
|
||||
is_responses_locked = receive_responses_lock_.exchange(false);
|
||||
CHECK(is_responses_locked);
|
||||
}
|
||||
VLOG(td_requests) << "End to wait for updates, returning object " << response.request_id << ' ' << response.object.get();
|
||||
VLOG(td_requests) << "End to wait for updates, returning object " << response.request_id << ' '
|
||||
<< response.object.get();
|
||||
return response;
|
||||
}
|
||||
|
||||
@ -530,9 +536,9 @@ class ClientManager::Impl final {
|
||||
Response receive(double timeout, bool include_responses, bool include_updates) {
|
||||
auto response = receiver_->receive(timeout, include_responses, include_updates);
|
||||
if (response.request_id == 0 && response.object != nullptr &&
|
||||
response.object->get_id() == td::td_api::updateAuthorizationState::ID &&
|
||||
static_cast<const td::td_api::updateAuthorizationState *>(response.object.get())
|
||||
->authorization_state_->get_id() == td::td_api::authorizationStateClosed::ID) {
|
||||
response.object->get_id() == td_api::updateAuthorizationState::ID &&
|
||||
static_cast<const td_api::updateAuthorizationState *>(response.object.get())->authorization_state_->get_id() ==
|
||||
td_api::authorizationStateClosed::ID) {
|
||||
auto lock = impls_mutex_.lock_write().move_as_ok();
|
||||
close_impl(response.client_id);
|
||||
}
|
||||
|
@ -8397,7 +8397,7 @@ void ContactsManager::on_load_user_full_from_database(UserId user_id, string val
|
||||
|
||||
Dependencies dependencies;
|
||||
dependencies.user_ids.insert(user_id);
|
||||
resolve_dependencies_force(td_, dependencies);
|
||||
resolve_dependencies_force(td_, dependencies, "user_full");
|
||||
|
||||
if (user_full->need_phone_number_privacy_exception && is_user_contact(user_id)) {
|
||||
user_full->need_phone_number_privacy_exception = false;
|
||||
@ -8581,7 +8581,7 @@ void ContactsManager::on_load_chat_full_from_database(ChatId chat_id, string val
|
||||
dependencies.user_ids.insert(participant.user_id);
|
||||
dependencies.user_ids.insert(participant.inviter_user_id);
|
||||
}
|
||||
resolve_dependencies_force(td_, dependencies);
|
||||
resolve_dependencies_force(td_, dependencies, "chat_full");
|
||||
|
||||
for (auto &participant : chat_full->participants) {
|
||||
get_bot_info_force(participant.user_id);
|
||||
@ -8668,7 +8668,7 @@ void ContactsManager::on_load_channel_full_from_database(ChannelId channel_id, s
|
||||
add_dialog_and_dependencies(dependencies, DialogId(channel_full->linked_channel_id));
|
||||
dependencies.chat_ids.insert(channel_full->migrated_from_chat_id);
|
||||
dependencies.user_ids.insert(channel_full->bot_user_ids.begin(), channel_full->bot_user_ids.end());
|
||||
resolve_dependencies_force(td_, dependencies);
|
||||
resolve_dependencies_force(td_, dependencies, "channel_full");
|
||||
|
||||
for (auto &user_id : channel_full->bot_user_ids) {
|
||||
get_bot_info_force(user_id);
|
||||
|
@ -43,30 +43,30 @@ void add_dialog_dependencies(Dependencies &dependencies, DialogId dialog_id) {
|
||||
}
|
||||
}
|
||||
|
||||
void resolve_dependencies_force(Td *td, const Dependencies &dependencies) {
|
||||
void resolve_dependencies_force(Td *td, const Dependencies &dependencies, const char *source) {
|
||||
for (auto user_id : dependencies.user_ids) {
|
||||
if (user_id.is_valid() && !td->contacts_manager_->have_user_force(user_id)) {
|
||||
LOG(ERROR) << "Can't find " << user_id;
|
||||
LOG(ERROR) << "Can't find " << user_id << " from " << source;
|
||||
}
|
||||
}
|
||||
for (auto chat_id : dependencies.chat_ids) {
|
||||
if (chat_id.is_valid() && !td->contacts_manager_->have_chat_force(chat_id)) {
|
||||
LOG(ERROR) << "Can't find " << chat_id;
|
||||
LOG(ERROR) << "Can't find " << chat_id << " from " << source;
|
||||
}
|
||||
}
|
||||
for (auto channel_id : dependencies.channel_ids) {
|
||||
if (channel_id.is_valid() && !td->contacts_manager_->have_channel_force(channel_id)) {
|
||||
LOG(ERROR) << "Can't find " << channel_id;
|
||||
LOG(ERROR) << "Can't find " << channel_id << " from " << source;
|
||||
}
|
||||
}
|
||||
for (auto secret_chat_id : dependencies.secret_chat_ids) {
|
||||
if (secret_chat_id.is_valid() && !td->contacts_manager_->have_secret_chat_force(secret_chat_id)) {
|
||||
LOG(ERROR) << "Can't find " << secret_chat_id;
|
||||
LOG(ERROR) << "Can't find " << secret_chat_id << " from " << source;
|
||||
}
|
||||
}
|
||||
for (auto dialog_id : dependencies.dialog_ids) {
|
||||
if (dialog_id.is_valid() && !td->messages_manager_->have_dialog_force(dialog_id)) {
|
||||
LOG(ERROR) << "Can't find " << dialog_id;
|
||||
LOG(ERROR) << "Can't find " << dialog_id << " from " << source;
|
||||
td->messages_manager_->force_create_dialog(dialog_id, "resolve_dependencies_force");
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,6 @@ void add_dialog_and_dependencies(Dependencies &dependencies, DialogId dialog_id)
|
||||
|
||||
void add_dialog_dependencies(Dependencies &dependencies, DialogId dialog_id);
|
||||
|
||||
void resolve_dependencies_force(Td *td, const Dependencies &dependencies);
|
||||
void resolve_dependencies_force(Td *td, const Dependencies &dependencies, const char *source);
|
||||
|
||||
} // namespace td
|
||||
|
@ -6,6 +6,7 @@
|
||||
//
|
||||
#include "td/telegram/MessageReplyInfo.h"
|
||||
|
||||
#include "td/telegram/ContactsManager.h"
|
||||
#include "td/telegram/ServerMessageId.h"
|
||||
|
||||
#include "td/utils/logging.h"
|
||||
@ -123,6 +124,23 @@ void MessageReplyInfo::add_reply(DialogId replier_dialog_id, MessageId reply_mes
|
||||
}
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::messageReplyInfo> MessageReplyInfo::get_message_reply_info_object(
|
||||
ContactsManager *contacts_manager) const {
|
||||
if (is_empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
vector<UserId> recent_replier_user_ids;
|
||||
for (auto recent_replier_dialog_id : recent_replier_dialog_ids) {
|
||||
if (recent_replier_dialog_id.get_type() == DialogType::User) {
|
||||
recent_replier_user_ids.push_back(recent_replier_dialog_id.get_user_id());
|
||||
}
|
||||
}
|
||||
return td_api::make_object<td_api::messageReplyInfo>(
|
||||
reply_count, contacts_manager->get_user_ids_object(recent_replier_user_ids, "get_message_reply_info_object"),
|
||||
last_read_inbox_message_id.get(), last_read_outbox_message_id.get(), max_message_id.get());
|
||||
}
|
||||
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const MessageReplyInfo &reply_info) {
|
||||
if (reply_info.is_comment) {
|
||||
return string_builder << reply_info.reply_count << " comments in " << reply_info.channel_id << " by "
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "td/telegram/ChannelId.h"
|
||||
#include "td/telegram/DialogId.h"
|
||||
#include "td/telegram/MessageId.h"
|
||||
#include "Td/telegram/td_api.h"
|
||||
#include "td/telegram/telegram_api.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
@ -17,6 +18,8 @@
|
||||
|
||||
namespace td {
|
||||
|
||||
class ContactsManager;
|
||||
|
||||
struct MessageReplyInfo {
|
||||
int32 reply_count = -1;
|
||||
int32 pts = -1;
|
||||
@ -44,6 +47,8 @@ struct MessageReplyInfo {
|
||||
|
||||
void add_reply(DialogId replier_dialog_id, MessageId reply_message_id);
|
||||
|
||||
td_api::object_ptr<td_api::messageReplyInfo> get_message_reply_info_object(ContactsManager *contacts_manager) const;
|
||||
|
||||
template <class StorerT>
|
||||
void store(StorerT &storer) const {
|
||||
CHECK(!is_empty());
|
||||
|
@ -6576,18 +6576,8 @@ td_api::object_ptr<td_api::messageInteractionInfo> MessagesManager::get_message_
|
||||
|
||||
td_api::object_ptr<td_api::messageReplyInfo> reply_info;
|
||||
if (is_visible_reply_info) {
|
||||
vector<UserId> recent_replier_user_ids;
|
||||
for (auto recent_replier_dialog_id : m->reply_info.recent_replier_dialog_ids) {
|
||||
if (recent_replier_dialog_id.get_type() == DialogType::User) {
|
||||
recent_replier_user_ids.push_back(recent_replier_dialog_id.get_user_id());
|
||||
}
|
||||
}
|
||||
reply_info = td_api::make_object<td_api::messageReplyInfo>(
|
||||
m->reply_info.reply_count,
|
||||
td_->contacts_manager_->get_user_ids_object(recent_replier_user_ids, "get_message_interaction_info_object"),
|
||||
m->reply_info.last_read_inbox_message_id.get(), m->reply_info.last_read_outbox_message_id.get(),
|
||||
m->reply_info.max_message_id.get());
|
||||
CHECK(reply_info->reply_count_ >= 0);
|
||||
reply_info = m->reply_info.get_message_reply_info_object(td_->contacts_manager_.get());
|
||||
CHECK(reply_info != nullptr);
|
||||
}
|
||||
|
||||
return td_api::make_object<td_api::messageInteractionInfo>(m->view_count, m->forward_count, std::move(reply_info));
|
||||
@ -14456,8 +14446,8 @@ unique_ptr<MessagesManager::Message> MessagesManager::do_delete_scheduled_messag
|
||||
auto result = treap_delete_message(v);
|
||||
|
||||
if (message_id.is_scheduled_server()) {
|
||||
size_t erased = d->scheduled_message_date.erase(message_id.get_scheduled_server_message_id());
|
||||
CHECK(erased != 0);
|
||||
size_t erased_count = d->scheduled_message_date.erase(message_id.get_scheduled_server_message_id());
|
||||
CHECK(erased_count != 0);
|
||||
}
|
||||
|
||||
cancel_send_deleted_message(d->dialog_id, result.get(), is_permanently_deleted);
|
||||
@ -14507,7 +14497,7 @@ void MessagesManager::load_dialogs(vector<DialogId> dialog_ids, Promise<Unit> &&
|
||||
add_dialog_dependencies(dependencies, dialog_id);
|
||||
}
|
||||
}
|
||||
resolve_dependencies_force(td_, dependencies);
|
||||
resolve_dependencies_force(td_, dependencies, "load_dialogs");
|
||||
|
||||
for (auto dialog_id : dialog_ids) {
|
||||
if (dialog_id.is_valid()) {
|
||||
@ -16125,14 +16115,23 @@ td_api::object_ptr<td_api::messageThreadInfo> MessagesManager::get_message_threa
|
||||
|
||||
Dialog *d = get_dialog(info.dialog_id);
|
||||
CHECK(d != nullptr);
|
||||
td_api::object_ptr<td_api::messageReplyInfo> reply_info;
|
||||
vector<td_api::object_ptr<td_api::message>> messages;
|
||||
messages.reserve(info.message_ids.size());
|
||||
for (auto message_id : info.message_ids) {
|
||||
auto message = get_message_object(d->dialog_id, get_message_force(d, message_id, "get_message_thread_info_object"));
|
||||
const Message *m = get_message_force(d, message_id, "get_message_thread_info_object");
|
||||
auto message = get_message_object(d->dialog_id, m);
|
||||
if (message != nullptr) {
|
||||
if (message->interaction_info_ != nullptr && message->interaction_info_->reply_info_ != nullptr) {
|
||||
reply_info = m->reply_info.get_message_reply_info_object(td_->contacts_manager_.get());
|
||||
CHECK(reply_info != nullptr);
|
||||
}
|
||||
messages.push_back(std::move(message));
|
||||
}
|
||||
}
|
||||
if (reply_info == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MessageId top_thread_message_id;
|
||||
td_api::object_ptr<td_api::draftMessage> draft_message;
|
||||
@ -16146,7 +16145,8 @@ td_api::object_ptr<td_api::messageThreadInfo> MessagesManager::get_message_threa
|
||||
}
|
||||
}
|
||||
return td_api::make_object<td_api::messageThreadInfo>(d->dialog_id.get(), top_thread_message_id.get(),
|
||||
std::move(messages), std::move(draft_message));
|
||||
std::move(reply_info), std::move(messages),
|
||||
std::move(draft_message));
|
||||
}
|
||||
|
||||
void MessagesManager::get_dialog_info_full(DialogId dialog_id, Promise<Unit> &&promise) {
|
||||
@ -20929,8 +20929,8 @@ void MessagesManager::on_get_dialog_message_by_date_success(DialogId dialog_id,
|
||||
}
|
||||
|
||||
void MessagesManager::on_get_dialog_message_by_date_fail(int64 random_id) {
|
||||
auto erased = get_dialog_message_by_date_results_.erase(random_id);
|
||||
CHECK(erased > 0);
|
||||
auto erased_count = get_dialog_message_by_date_results_.erase(random_id);
|
||||
CHECK(erased_count > 0);
|
||||
}
|
||||
|
||||
tl_object_ptr<td_api::message> MessagesManager::get_dialog_message_by_date_object(int64 random_id) {
|
||||
@ -21199,7 +21199,7 @@ void MessagesManager::on_get_history_from_database(DialogId dialog_id, MessageId
|
||||
is_first = false;
|
||||
pos++;
|
||||
}
|
||||
resolve_dependencies_force(td_, dependencies);
|
||||
resolve_dependencies_force(td_, dependencies, "get_history");
|
||||
|
||||
if (from_the_end && !last_added_message_id.is_valid() && last_received_message_id < d->first_database_message_id &&
|
||||
!d->have_full_history) {
|
||||
@ -21514,7 +21514,7 @@ void MessagesManager::on_get_scheduled_messages_from_database(DialogId dialog_id
|
||||
added_message_ids.push_back(m->message_id);
|
||||
}
|
||||
}
|
||||
resolve_dependencies_force(td_, dependencies);
|
||||
resolve_dependencies_force(td_, dependencies, "get_scheduled_messages");
|
||||
|
||||
// for (auto message_id : added_message_ids) {
|
||||
// send_update_new_message(d, get_message(d, message_id));
|
||||
@ -30329,7 +30329,7 @@ MessagesManager::Message *MessagesManager::on_get_message_from_database(DialogId
|
||||
|
||||
Dependencies dependencies;
|
||||
add_message_dependencies(dependencies, d->dialog_id, m.get());
|
||||
resolve_dependencies_force(td_, dependencies);
|
||||
resolve_dependencies_force(td_, dependencies, "get_message");
|
||||
|
||||
m->have_previous = false;
|
||||
m->have_next = false;
|
||||
@ -33331,7 +33331,7 @@ unique_ptr<MessagesManager::Dialog> MessagesManager::parse_dialog(DialogId dialo
|
||||
if (d->draft_message != nullptr) {
|
||||
add_formatted_text_dependencies(dependencies, &d->draft_message->input_message_text.text);
|
||||
}
|
||||
resolve_dependencies_force(td_, dependencies);
|
||||
resolve_dependencies_force(td_, dependencies, "parse_dialog");
|
||||
|
||||
return d;
|
||||
}
|
||||
@ -34523,7 +34523,7 @@ void MessagesManager::on_binlog_events(vector<BinlogEvent> &&events) {
|
||||
Dependencies dependencies;
|
||||
add_dialog_dependencies(dependencies, dialog_id);
|
||||
add_message_dependencies(dependencies, dialog_id, m.get());
|
||||
resolve_dependencies_force(td_, dependencies);
|
||||
resolve_dependencies_force(td_, dependencies, "SendMessageLogEvent");
|
||||
|
||||
m->content =
|
||||
dup_message_content(td_, dialog_id, m->content.get(), MessageContentDupType::Send, MessageCopyOptions());
|
||||
@ -34553,7 +34553,7 @@ void MessagesManager::on_binlog_events(vector<BinlogEvent> &&events) {
|
||||
Dependencies dependencies;
|
||||
add_dialog_dependencies(dependencies, dialog_id);
|
||||
add_message_dependencies(dependencies, dialog_id, m.get());
|
||||
resolve_dependencies_force(td_, dependencies);
|
||||
resolve_dependencies_force(td_, dependencies, "SendBotStartMessageLogEvent");
|
||||
|
||||
auto bot_user_id = log_event.bot_user_id;
|
||||
if (!td_->contacts_manager_->have_user_force(bot_user_id)) {
|
||||
@ -34590,7 +34590,7 @@ void MessagesManager::on_binlog_events(vector<BinlogEvent> &&events) {
|
||||
Dependencies dependencies;
|
||||
add_dialog_dependencies(dependencies, dialog_id);
|
||||
add_message_dependencies(dependencies, dialog_id, m.get());
|
||||
resolve_dependencies_force(td_, dependencies);
|
||||
resolve_dependencies_force(td_, dependencies, "SendInlineQueryResultMessageLogEvent");
|
||||
|
||||
m->content = dup_message_content(td_, dialog_id, m->content.get(), MessageContentDupType::SendViaBot,
|
||||
MessageCopyOptions());
|
||||
@ -34619,7 +34619,7 @@ void MessagesManager::on_binlog_events(vector<BinlogEvent> &&events) {
|
||||
Dependencies dependencies;
|
||||
add_dialog_dependencies(dependencies, dialog_id);
|
||||
add_message_dependencies(dependencies, dialog_id, m.get());
|
||||
resolve_dependencies_force(td_, dependencies);
|
||||
resolve_dependencies_force(td_, dependencies, "SendScreenshotTakenNotificationMessageLogEvent");
|
||||
|
||||
auto result_message = continue_send_message(dialog_id, std::move(m), event.id_);
|
||||
if (result_message != nullptr) {
|
||||
@ -34646,7 +34646,7 @@ void MessagesManager::on_binlog_events(vector<BinlogEvent> &&events) {
|
||||
for (auto &m : messages) {
|
||||
add_message_dependencies(dependencies, to_dialog_id, m.get());
|
||||
}
|
||||
resolve_dependencies_force(td_, dependencies);
|
||||
resolve_dependencies_force(td_, dependencies, "ForwardMessagesLogEvent");
|
||||
|
||||
Dialog *to_dialog = get_dialog_force(to_dialog_id);
|
||||
if (to_dialog == nullptr) {
|
||||
@ -35128,7 +35128,7 @@ void MessagesManager::on_binlog_events(vector<BinlogEvent> &&events) {
|
||||
auto dialog_id = log_event.dialog_id_;
|
||||
Dependencies dependencies;
|
||||
add_dialog_dependencies(dependencies, dialog_id);
|
||||
resolve_dependencies_force(td_, dependencies);
|
||||
resolve_dependencies_force(td_, dependencies, "GetDialogFromServerLogEvent");
|
||||
|
||||
get_dialog_force(dialog_id); // load it if exists
|
||||
|
||||
|
@ -643,7 +643,7 @@ void PollManager::unregister_poll(PollId poll_id, FullMessageId full_message_id,
|
||||
}
|
||||
LOG(INFO) << "Unregister " << poll_id << " from " << full_message_id << " from " << source;
|
||||
auto &message_ids = poll_messages_[poll_id];
|
||||
auto is_deleted = message_ids.erase(full_message_id);
|
||||
auto is_deleted = message_ids.erase(full_message_id) > 0;
|
||||
LOG_CHECK(is_deleted) << source << " " << poll_id << " " << full_message_id;
|
||||
if (message_ids.empty()) {
|
||||
poll_messages_.erase(poll_id);
|
||||
@ -1653,7 +1653,7 @@ void PollManager::on_binlog_events(vector<BinlogEvent> &&events) {
|
||||
|
||||
Dependencies dependencies;
|
||||
add_dialog_dependencies(dependencies, dialog_id); // do not load the dialog itself
|
||||
resolve_dependencies_force(td_, dependencies);
|
||||
resolve_dependencies_force(td_, dependencies, "SetPollAnswerLogEvent");
|
||||
|
||||
do_set_poll_answer(log_event.poll_id_, log_event.full_message_id_, std::move(log_event.options_), event.id_,
|
||||
Auto());
|
||||
@ -1672,7 +1672,7 @@ void PollManager::on_binlog_events(vector<BinlogEvent> &&events) {
|
||||
|
||||
Dependencies dependencies;
|
||||
add_dialog_dependencies(dependencies, dialog_id); // do not load the dialog itself
|
||||
resolve_dependencies_force(td_, dependencies);
|
||||
resolve_dependencies_force(td_, dependencies, "StopPollLogEvent");
|
||||
|
||||
do_stop_poll(log_event.poll_id_, log_event.full_message_id_, nullptr, event.id_, Auto());
|
||||
break;
|
||||
|
@ -3581,8 +3581,8 @@ void StickersManager::unregister_dice(const string &emoji, int32 value, FullMess
|
||||
LOG(INFO) << "Unregister dice " << emoji << " with value " << value << " from " << full_message_id << " from "
|
||||
<< source;
|
||||
auto &message_ids = dice_messages_[emoji];
|
||||
message_ids.erase(full_message_id);
|
||||
LOG(INFO) << source << " " << emoji << " " << value << " " << full_message_id;
|
||||
auto is_deleted = message_ids.erase(full_message_id) > 0;
|
||||
LOG_CHECK(is_deleted) << source << " " << emoji << " " << value << " " << full_message_id;
|
||||
|
||||
if (message_ids.empty()) {
|
||||
dice_messages_.erase(emoji);
|
||||
|
@ -103,7 +103,7 @@ class Td final : public NetQueryCallback {
|
||||
~Td() override;
|
||||
|
||||
struct Options {
|
||||
std::shared_ptr<td::NetQueryStats> net_query_stats;
|
||||
std::shared_ptr<NetQueryStats> net_query_stats;
|
||||
};
|
||||
|
||||
Td(unique_ptr<TdCallback> callback, Options options);
|
||||
|
@ -741,8 +741,9 @@ void WebPagesManager::unregister_web_page(WebPageId web_page_id, FullMessageId f
|
||||
if (find_message_ids == web_page_messages_.end()) { return; }
|
||||
auto &message_ids = find_message_ids->second;
|
||||
// End custom-patches
|
||||
auto is_deleted = message_ids.erase(full_message_id);
|
||||
auto is_deleted = message_ids.erase(full_message_id) > 0;
|
||||
if (!is_deleted) { return; }
|
||||
LOG_CHECK(is_deleted) << source << " " << web_page_id << " " << full_message_id;
|
||||
|
||||
if (message_ids.empty()) {
|
||||
web_page_messages_.erase(web_page_id);
|
||||
|
@ -13,8 +13,8 @@
|
||||
|
||||
#include "td/telegram/ClientActor.h"
|
||||
#include "td/telegram/Log.h"
|
||||
#include "td/telegram/td_api_json.h"
|
||||
#include "td/telegram/Td.h" // for VERBOSITY_NAME(td_requests)
|
||||
#include "td/telegram/td_api_json.h"
|
||||
|
||||
#include "td/utils/base64.h"
|
||||
#include "td/utils/buffer.h"
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "td/utils/buffer.h"
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/port/FileFd.h"
|
||||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/Status.h"
|
||||
|
@ -2416,7 +2416,7 @@ class FileManager::ForceUploadActor : public Actor {
|
||||
if (callback_.empty()) {
|
||||
return;
|
||||
}
|
||||
send_closure(std::move(callback_), &ForceUploadActor::on_upload_error, td::Status::Error("Cancelled"));
|
||||
send_closure(std::move(callback_), &ForceUploadActor::on_upload_error, Status::Error("Cancelled"));
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "td/utils/buffer.h"
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/logging.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "td/utils/Closure.h"
|
||||
#include "td/utils/Heap.h"
|
||||
#include "td/utils/List.h"
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/MovableValue.h"
|
||||
#include "td/utils/MpscPollableQueue.h"
|
||||
#include "td/utils/ObjectPool.h"
|
||||
|
@ -7,6 +7,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/ScopeGuard.h"
|
||||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/Status.h"
|
||||
|
@ -368,7 +368,7 @@ class TQueueImpl : public TQueue {
|
||||
|
||||
void schedule_queue_gc(QueueId queue_id, Queue &q, int32 gc_at) {
|
||||
if (q.gc_at != 0) {
|
||||
bool is_deleted = queue_gc_at_.erase({q.gc_at, queue_id});
|
||||
bool is_deleted = queue_gc_at_.erase({q.gc_at, queue_id}) > 0;
|
||||
CHECK(is_deleted);
|
||||
}
|
||||
q.gc_at = gc_at;
|
||||
|
@ -272,6 +272,7 @@ if (TDUTILS_MIME_TYPE)
|
||||
endif()
|
||||
|
||||
set(TDUTILS_TEST_SOURCE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/bitmask.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/buffer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/ConcurrentHashMap.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/crypto.cpp
|
||||
|
@ -472,8 +472,8 @@ void FileFd::remove_local_lock(const string &path) {
|
||||
if (!path.empty()) {
|
||||
VLOG(fd) << "Unlock file \"" << path << '"';
|
||||
std::unique_lock<std::mutex> lock(in_process_lock_mutex);
|
||||
auto erased = locked_files.erase(path);
|
||||
CHECK(erased > 0);
|
||||
auto erased_count = locked_files.erase(path);
|
||||
CHECK(erased_count > 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
246
tdutils/test/bitmask.cpp
Normal file
246
tdutils/test/bitmask.cpp
Normal file
@ -0,0 +1,246 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
#include "td/utils/tests.h"
|
||||
#include "td/utils/misc.h"
|
||||
#include "td/utils/utf8.h"
|
||||
|
||||
namespace td {
|
||||
class RangeSet {
|
||||
template <class T>
|
||||
static auto find(T &ranges, int64 begin) {
|
||||
return std::lower_bound(ranges.begin(), ranges.end(), begin,
|
||||
[](const Range &range, int64 begin) { return range.end < begin; });
|
||||
}
|
||||
auto find(int64 begin) const {
|
||||
return find(ranges_, begin);
|
||||
}
|
||||
auto find(int64 begin) {
|
||||
return find(ranges_, begin);
|
||||
}
|
||||
|
||||
public:
|
||||
struct Range {
|
||||
int64 begin;
|
||||
int64 end;
|
||||
};
|
||||
|
||||
static constexpr int64 BitSize = 1024;
|
||||
static constexpr int64 MaxPartSize = 16 * 1024 * 1024;
|
||||
|
||||
RangeSet() = default;
|
||||
|
||||
static RangeSet create_one_range(int64 end, int64 begin = 0) {
|
||||
RangeSet res;
|
||||
res.ranges_.push_back({begin, end});
|
||||
return res;
|
||||
}
|
||||
static td::Result<RangeSet> decode(CSlice data) {
|
||||
if (!check_utf8(data)) {
|
||||
return Status::Error("Invalid encoding");
|
||||
}
|
||||
uint32 curr = 0;
|
||||
bool is_empty = false;
|
||||
RangeSet res;
|
||||
for (auto begin = data.ubegin(); begin != data.uend();) {
|
||||
uint32 size;
|
||||
begin = next_utf8_unsafe(begin, &size, "RangeSet");
|
||||
|
||||
if (!is_empty && size != 0) {
|
||||
res.ranges_.push_back({curr * BitSize, (curr + size) * BitSize});
|
||||
}
|
||||
curr += size;
|
||||
is_empty = !is_empty;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string encode(int64 prefix_size = -1) const {
|
||||
std::vector<uint32> sizes;
|
||||
uint32 all_end = 0;
|
||||
|
||||
if (prefix_size != -1) {
|
||||
prefix_size = (prefix_size + BitSize - 1) / BitSize * BitSize;
|
||||
}
|
||||
for (auto it : ranges_) {
|
||||
if (prefix_size != -1 && it.begin >= prefix_size) {
|
||||
break;
|
||||
}
|
||||
if (prefix_size != -1 && it.end > prefix_size) {
|
||||
it.end = prefix_size;
|
||||
}
|
||||
|
||||
CHECK(it.begin % BitSize == 0);
|
||||
CHECK(it.end % BitSize == 0);
|
||||
uint32 begin = narrow_cast<uint32>(it.begin / BitSize);
|
||||
uint32 end = narrow_cast<uint32>(it.end / BitSize);
|
||||
if (sizes.empty()) {
|
||||
if (begin != 0) {
|
||||
sizes.push_back(0);
|
||||
sizes.push_back(begin);
|
||||
}
|
||||
} else {
|
||||
sizes.push_back(begin - all_end);
|
||||
}
|
||||
sizes.push_back(end - begin);
|
||||
all_end = end;
|
||||
}
|
||||
|
||||
std::string res;
|
||||
for (auto c : sizes) {
|
||||
append_utf8_character(res, c);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int64 get_ready_prefix_size(int64 offset, int64 file_size = -1) const {
|
||||
auto it = find(offset);
|
||||
if (it == ranges_.end()) {
|
||||
return 0;
|
||||
}
|
||||
if (it->begin > offset) {
|
||||
return 0;
|
||||
}
|
||||
CHECK(offset >= it->begin);
|
||||
CHECK(offset <= it->end);
|
||||
auto end = it->end;
|
||||
if (file_size != -1 && end > file_size) {
|
||||
end = file_size;
|
||||
}
|
||||
if (end < offset) {
|
||||
return 0;
|
||||
}
|
||||
return end - offset;
|
||||
}
|
||||
int64 get_total_size(int64 file_size) const {
|
||||
int64 res = 0;
|
||||
for (auto it : ranges_) {
|
||||
if (it.begin >= file_size) {
|
||||
break;
|
||||
}
|
||||
if (it.end > file_size) {
|
||||
it.end = file_size;
|
||||
}
|
||||
res += it.end - it.begin;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
int64 get_ready_parts(int64 offset_part, int64 part_size) const {
|
||||
auto offset = offset_part * part_size;
|
||||
auto it = find(offset);
|
||||
if (it == ranges_.end()) {
|
||||
return 0;
|
||||
}
|
||||
if (it->begin > offset) {
|
||||
return 0;
|
||||
}
|
||||
return (it->end - offset) / part_size;
|
||||
}
|
||||
|
||||
bool is_ready(int64 begin, int64 end) const {
|
||||
auto it = find(begin);
|
||||
if (it == ranges_.end()) {
|
||||
return false;
|
||||
}
|
||||
return it->begin <= begin && end <= it->end;
|
||||
}
|
||||
|
||||
void set(int64 begin, int64 end) {
|
||||
CHECK(begin % BitSize == 0);
|
||||
CHECK(end % BitSize == 0);
|
||||
// 1. skip all with r.end < begin
|
||||
auto it_begin = find(begin);
|
||||
|
||||
// 2. combine with all r.begin <= end
|
||||
auto it_end = it_begin;
|
||||
for (; it_end != ranges_.end() && it_end->begin <= end; ++it_end) {
|
||||
}
|
||||
|
||||
if (it_begin == it_end) {
|
||||
ranges_.insert(it_begin, Range{begin, end});
|
||||
} else {
|
||||
begin = std::min(begin, it_begin->begin);
|
||||
--it_end;
|
||||
end = std::max(end, it_end->end);
|
||||
*it_end = Range{begin, end};
|
||||
ranges_.erase(it_begin, it_end);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<int32> as_vector(int32 part_size) const {
|
||||
std::vector<int32> res;
|
||||
for (auto it : ranges_) {
|
||||
auto begin = narrow_cast<int32>((it.begin + part_size - 1) / part_size);
|
||||
auto end = narrow_cast<int32>(it.end / part_size);
|
||||
while (begin < end) {
|
||||
res.push_back(begin++);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<Range> ranges_;
|
||||
};
|
||||
|
||||
TEST(Bitmask, simple) {
|
||||
auto validate_encoding = [](auto &rs) {
|
||||
auto str = rs.encode();
|
||||
LOG(ERROR) << str.size();
|
||||
RangeSet rs2 = RangeSet::decode(str).move_as_ok();
|
||||
auto str2 = rs2.encode();
|
||||
rs = std::move(rs2);
|
||||
CHECK(str2 == str);
|
||||
};
|
||||
{
|
||||
RangeSet rs;
|
||||
int32 S = 128 * 1024;
|
||||
int32 O = S * 5000;
|
||||
for (int i = 1; i < 30; i++) {
|
||||
if (i % 2 == 0) {
|
||||
rs.set(O + S * i, O + S * (i + 1));
|
||||
}
|
||||
}
|
||||
validate_encoding(rs);
|
||||
}
|
||||
{
|
||||
RangeSet rs;
|
||||
int32 S = 1024;
|
||||
auto get = [&](auto p) {
|
||||
return rs.get_ready_prefix_size(p * S) / S;
|
||||
};
|
||||
auto set = [&](auto l, auto r) {
|
||||
rs.set(l * S, r * S);
|
||||
validate_encoding(rs);
|
||||
ASSERT_TRUE(rs.is_ready(l * S, r * S));
|
||||
ASSERT_TRUE(get(l) >= (r - l));
|
||||
};
|
||||
set(6, 7);
|
||||
ASSERT_EQ(1, get(6));
|
||||
ASSERT_EQ(0, get(5));
|
||||
set(8, 9);
|
||||
ASSERT_EQ(0, get(7));
|
||||
set(7, 8);
|
||||
ASSERT_EQ(2, get(7));
|
||||
ASSERT_EQ(3, get(6));
|
||||
set(3, 5);
|
||||
ASSERT_EQ(1, get(4));
|
||||
set(4, 6);
|
||||
ASSERT_EQ(5, get(4));
|
||||
set(10, 11);
|
||||
set(9, 10);
|
||||
ASSERT_EQ(8, get(3));
|
||||
set(14, 16);
|
||||
set(12, 13);
|
||||
ASSERT_EQ(8, get(3));
|
||||
|
||||
ASSERT_EQ(10, rs.get_ready_prefix_size(S * 3, S * 3 + 10));
|
||||
ASSERT_TRUE(!rs.is_ready(S*11, S *12));
|
||||
ASSERT_EQ(3, rs.get_ready_parts(2, S * 2));
|
||||
ASSERT_EQ(std::vector<int32>({2, 3, 4, 7}), rs.as_vector(S * 2) );
|
||||
}
|
||||
}
|
||||
} // namespace td
|
@ -32,12 +32,16 @@ target_link_libraries(all_tests PRIVATE tdcore tdclient)
|
||||
|
||||
if (NOT CMAKE_CROSSCOMPILING OR EMSCRIPTEN)
|
||||
#Tests
|
||||
add_executable(test-tdutils ${TESTS_MAIN} ${TDUTILS_TEST_SOURCE})
|
||||
add_executable(run_all_tests ${TESTS_MAIN} ${TD_TEST_SOURCE})
|
||||
if (CLANG AND NOT CYGWIN AND NOT EMSCRIPTEN AND NOT (CMAKE_HOST_SYSTEM_NAME MATCHES "OpenBSD"))
|
||||
target_compile_options(test-tdutils PUBLIC -fsanitize=undefined -fno-sanitize=vptr)
|
||||
target_compile_options(run_all_tests PUBLIC -fsanitize=undefined -fno-sanitize=vptr)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined -fno-sanitize=vptr")
|
||||
endif()
|
||||
target_include_directories(run_all_tests PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
|
||||
target_include_directories(test-tdutils PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
|
||||
target_link_libraries(test-tdutils PRIVATE tdutils)
|
||||
target_link_libraries(run_all_tests PRIVATE tdcore tdclient)
|
||||
|
||||
if (CLANG)
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
|
||||
@ -1008,8 +1009,8 @@ TEST(Client, Close) {
|
||||
receive_count++;
|
||||
{
|
||||
std::unique_lock<std::mutex> guard(request_ids_mutex);
|
||||
size_t erase_count = request_ids.erase(response.id);
|
||||
CHECK(erase_count > 0);
|
||||
size_t erased_count = request_ids.erase(response.id);
|
||||
CHECK(erased_count > 0);
|
||||
}
|
||||
}
|
||||
if (can_stop_receive && receive_count == send_count) {
|
||||
@ -1070,8 +1071,8 @@ TEST(Client, ManagerClose) {
|
||||
receive_count++;
|
||||
{
|
||||
std::unique_lock<std::mutex> guard(request_ids_mutex);
|
||||
size_t erase_count = request_ids.erase(response.request_id);
|
||||
CHECK(erase_count > 0);
|
||||
size_t erased_count = request_ids.erase(response.request_id);
|
||||
CHECK(erased_count > 0);
|
||||
}
|
||||
}
|
||||
if (can_stop_receive && receive_count == send_count) {
|
||||
|
Loading…
Reference in New Issue
Block a user