mirror of
https://github.com/ars3niy/tdlib-purple
synced 2025-09-01 14:35:11 +00:00
Added a real test case with login sequence
This commit is contained in:
@@ -44,6 +44,14 @@ Copy the .so to libpurple plugins directory.
|
|||||||
|
|
||||||
It's good to have telegram-purple installed as well since its icon is used at the moment.
|
It's good to have telegram-purple installed as well since its icon is used at the moment.
|
||||||
|
|
||||||
|
## Regression test
|
||||||
|
|
||||||
|
Build google test library and `make install` it somewhere
|
||||||
|
|
||||||
|
Run cmake with '-DGTEST_PATH=/path/to/gtest'
|
||||||
|
|
||||||
|
`make run-tests` or `test/tests` or `valgrind test/tests`
|
||||||
|
|
||||||
## GPL compatibility: building tdlib with OpenSSL 3.0
|
## GPL compatibility: building tdlib with OpenSSL 3.0
|
||||||
|
|
||||||
OpenSSL versions prior to 3.0 branch have license with advertisement clause, making it incompatible with GPL. If this is a concern, a possible solution is to build with OpenSSL 3.0 which uses Apache 2.0 license.
|
OpenSSL versions prior to 3.0 branch have license with advertisement clause, making it incompatible with GPL. If this is a concern, a possible solution is to build with OpenSSL 3.0 which uses Apache 2.0 license.
|
||||||
|
@@ -275,8 +275,9 @@ void PurpleTdClient::setPurpleConnectionInProgress()
|
|||||||
purple_debug_misc(config::pluginId, "Connection in progress\n");
|
purple_debug_misc(config::pluginId, "Connection in progress\n");
|
||||||
PurpleConnection *gc = purple_account_get_connection(m_account);
|
PurpleConnection *gc = purple_account_get_connection(m_account);
|
||||||
|
|
||||||
|
if (PURPLE_CONNECTION_IS_CONNECTED(gc))
|
||||||
|
purple_blist_remove_account(m_account);
|
||||||
purple_connection_set_state (gc, PURPLE_CONNECTING);
|
purple_connection_set_state (gc, PURPLE_CONNECTING);
|
||||||
purple_blist_remove_account(m_account);
|
|
||||||
purple_connection_update_progress(gc, "Connecting", 1, 3);
|
purple_connection_update_progress(gc, "Connecting", 1, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -8,6 +8,7 @@ add_executable(tests EXCLUDE_FROM_ALL
|
|||||||
testsuite.cpp
|
testsuite.cpp
|
||||||
test-transceiver.cpp
|
test-transceiver.cpp
|
||||||
libpurple-mock.cpp
|
libpurple-mock.cpp
|
||||||
|
printout.cpp
|
||||||
|
|
||||||
../tdlib-purple.cpp
|
../tdlib-purple.cpp
|
||||||
../td-client.cpp
|
../td-client.cpp
|
||||||
|
@@ -64,7 +64,7 @@ void purple_account_destroy(PurpleAccount *account)
|
|||||||
{
|
{
|
||||||
free(account->username);
|
free(account->username);
|
||||||
free(account->alias);
|
free(account->alias);
|
||||||
free(account);
|
delete account;
|
||||||
}
|
}
|
||||||
|
|
||||||
void purple_blist_add_account(PurpleAccount *account)
|
void purple_blist_add_account(PurpleAccount *account)
|
||||||
@@ -89,7 +89,7 @@ void purple_blist_remove_buddy(PurpleBuddy *buddy)
|
|||||||
// TODO add event
|
// TODO add event
|
||||||
free(buddy->name);
|
free(buddy->name);
|
||||||
free(buddy->alias);
|
free(buddy->alias);
|
||||||
free(buddy);
|
delete buddy;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *purple_buddy_get_alias_only(PurpleBuddy *buddy)
|
const char *purple_buddy_get_alias_only(PurpleBuddy *buddy)
|
||||||
@@ -176,7 +176,7 @@ PurpleConversation *purple_conversation_new(PurpleConversationType type,
|
|||||||
void purple_conversation_destroy(PurpleConversation *conv)
|
void purple_conversation_destroy(PurpleConversation *conv)
|
||||||
{
|
{
|
||||||
free(conv->name);
|
free(conv->name);
|
||||||
free(conv);
|
delete conv;
|
||||||
}
|
}
|
||||||
|
|
||||||
void purple_conversation_write(PurpleConversation *conv, const char *who,
|
void purple_conversation_write(PurpleConversation *conv, const char *who,
|
||||||
@@ -309,7 +309,7 @@ void purple_xfer_unref(PurpleXfer *xfer)
|
|||||||
{
|
{
|
||||||
if (--xfer->ref == 0) {
|
if (--xfer->ref == 0) {
|
||||||
free(xfer->who);
|
free(xfer->who);
|
||||||
free(xfer);
|
delete xfer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1219
test/printout.cpp
Normal file
1219
test/printout.cpp
Normal file
File diff suppressed because it is too large
Load Diff
9
test/printout.h
Normal file
9
test/printout.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#ifndef _PRINTOUT_H
|
||||||
|
#define _PRINTOUT_H
|
||||||
|
|
||||||
|
#include <td/telegram/td_api.hpp>
|
||||||
|
|
||||||
|
std::string requestToString(const td::td_api::Function &req);
|
||||||
|
std::string responseToString(const td::td_api::Object &object);
|
||||||
|
|
||||||
|
#endif
|
@@ -1,17 +1,15 @@
|
|||||||
#include "test-transceiver.h"
|
#include "test-transceiver.h"
|
||||||
|
#include "printout.h"
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
static std::string requestToString(const td::td_api::Function &req)
|
using namespace td::td_api;
|
||||||
{
|
|
||||||
return "whatever";
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestTransceiver::send(td::Client::Request &&request)
|
void TestTransceiver::send(td::Client::Request &&request)
|
||||||
{
|
{
|
||||||
m_requests.push(std::move(request));
|
m_requests.push(std::move(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestTransceiver::verifyRequest(const td::td_api::Function &request)
|
void TestTransceiver::verifyRequest(const Function &request)
|
||||||
{
|
{
|
||||||
m_lastRequestIds.clear();
|
m_lastRequestIds.clear();
|
||||||
verifyRequestImpl(request);
|
verifyRequestImpl(request);
|
||||||
@@ -20,10 +18,10 @@ void TestTransceiver::verifyRequest(const td::td_api::Function &request)
|
|||||||
verifyNoRequests();
|
verifyNoRequests();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestTransceiver::verifyRequests(const std::vector<td::td_api::Function> &requests)
|
void TestTransceiver::verifyRequests(const std::vector<Function> &requests)
|
||||||
{
|
{
|
||||||
m_lastRequestIds.clear();
|
m_lastRequestIds.clear();
|
||||||
for (const td::td_api::Function &req: requests) {
|
for (const Function &req: requests) {
|
||||||
verifyRequestImpl(req);
|
verifyRequestImpl(req);
|
||||||
m_lastRequestIds.push_back(m_requests.front().id);
|
m_lastRequestIds.push_back(m_requests.front().id);
|
||||||
m_requests.pop();
|
m_requests.pop();
|
||||||
@@ -31,12 +29,67 @@ void TestTransceiver::verifyRequests(const std::vector<td::td_api::Function> &re
|
|||||||
verifyNoRequests();
|
verifyNoRequests();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestTransceiver::verifyRequestImpl(const td::td_api::Function &request)
|
static void compare(const Function &actual, const Function &expected)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void compare(const setTdlibParameters &actual, const setTdlibParameters &expected)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(expected.parameters_->database_directory_, actual.parameters_->database_directory_);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void compare(const checkDatabaseEncryptionKey &actual, const checkDatabaseEncryptionKey &expected)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(expected.encryption_key_, actual.encryption_key_);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void compare(const setAuthenticationPhoneNumber &actual, const setAuthenticationPhoneNumber &expected)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(expected.phone_number_, actual.phone_number_);
|
||||||
|
EXPECT_TRUE((expected.settings_ != nullptr) == (actual.settings_ != nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void compareRequests(const Function &actual, const Function &expected)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(expected.get_id(), actual.get_id()) << "Wrong request type: expected " << requestToString(expected);
|
||||||
|
|
||||||
|
#define C(class) case class::ID: \
|
||||||
|
compare(static_cast<const class &>(actual), static_cast<const class &>(expected)); \
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (actual.get_id()) {
|
||||||
|
C(setTdlibParameters)
|
||||||
|
C(checkDatabaseEncryptionKey)
|
||||||
|
C(setAuthenticationPhoneNumber)
|
||||||
|
default:
|
||||||
|
compare(actual, expected);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestTransceiver::verifyRequestImpl(const Function &request)
|
||||||
{
|
{
|
||||||
EXPECT_FALSE(m_requests.empty()) << "Missing request: expected " << requestToString(request);
|
EXPECT_FALSE(m_requests.empty()) << "Missing request: expected " << requestToString(request);
|
||||||
|
|
||||||
|
std::cout << "Received request " << m_requests.front().id << ": " << requestToString(*m_requests.front().function) << "\n";
|
||||||
|
compareRequests(*m_requests.front().function, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestTransceiver::verifyNoRequests()
|
void TestTransceiver::verifyNoRequests()
|
||||||
{
|
{
|
||||||
EXPECT_TRUE(m_requests.empty()) << "Unexpected request: " << requestToString(*m_requests.front().function);
|
EXPECT_TRUE(m_requests.empty()) << "Unexpected request: " << requestToString(*m_requests.front().function);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestTransceiver::update(object_ptr<Object> object)
|
||||||
|
{
|
||||||
|
std::cout << "Sending update: " << responseToString(*object) << "\n";
|
||||||
|
receive({0, std::move(object)});
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestTransceiver::reply(object_ptr<Object> object)
|
||||||
|
{
|
||||||
|
EXPECT_GE(1u, m_lastRequestIds.size()) << "No requests to reply to";
|
||||||
|
std::cout << "Replying to request " << m_lastRequestIds.front() << ": " << responseToString(*object) << "\n";
|
||||||
|
receive({m_lastRequestIds.front(), std::move(object)});
|
||||||
|
m_lastRequestIds.erase(m_lastRequestIds.begin());
|
||||||
|
}
|
||||||
|
@@ -11,6 +11,8 @@ public:
|
|||||||
void verifyRequest(const td::td_api::Function &request);
|
void verifyRequest(const td::td_api::Function &request);
|
||||||
void verifyRequests(const std::vector<td::td_api::Function> &requests);
|
void verifyRequests(const std::vector<td::td_api::Function> &requests);
|
||||||
void verifyNoRequests();
|
void verifyNoRequests();
|
||||||
|
void update(td::td_api::object_ptr<td::td_api::Object> object);
|
||||||
|
void reply(td::td_api::object_ptr<td::td_api::Object> object);
|
||||||
private:
|
private:
|
||||||
std::queue<td::Client::Request> m_requests;
|
std::queue<td::Client::Request> m_requests;
|
||||||
std::vector<uint64_t> m_lastRequestIds;
|
std::vector<uint64_t> m_lastRequestIds;
|
||||||
|
@@ -2,32 +2,128 @@
|
|||||||
#include "tdlib-purple.h"
|
#include "tdlib-purple.h"
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
using namespace td::td_api;
|
||||||
|
|
||||||
class CommTest: public testing::Test {
|
class CommTest: public testing::Test {
|
||||||
public:
|
public:
|
||||||
CommTest();
|
CommTest();
|
||||||
~CommTest();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::string phoneNumber = "1234567";
|
const std::string phoneNumber = "1234567";
|
||||||
|
const int selfId = 1;
|
||||||
|
const std::string selfFirstName = "Isaac";
|
||||||
|
const std::string selfLastName = "Newton";
|
||||||
|
|
||||||
TestTransceiver tgl;
|
TestTransceiver tgl;
|
||||||
PurplePlugin purplePlugin;
|
PurplePlugin purplePlugin;
|
||||||
PurpleAccount *account;
|
PurpleAccount *account;
|
||||||
|
PurpleConnection *connection;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void SetUp() override;
|
||||||
|
void TearDown() override;
|
||||||
|
void login();
|
||||||
};
|
};
|
||||||
|
|
||||||
CommTest::CommTest()
|
CommTest::CommTest()
|
||||||
{
|
{
|
||||||
tgprpl_set_test_backend(&tgl);
|
tgprpl_set_test_backend(&tgl);
|
||||||
purple_init_plugin(&purplePlugin);
|
purple_init_plugin(&purplePlugin);
|
||||||
account = purple_account_new(phoneNumber.c_str(), NULL);
|
|
||||||
((PurplePluginProtocolInfo *)purplePlugin.info->extra_info)->login(account);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CommTest::~CommTest()
|
void CommTest::SetUp()
|
||||||
{
|
{
|
||||||
|
account = purple_account_new(phoneNumber.c_str(), NULL);
|
||||||
|
connection = new PurpleConnection;
|
||||||
|
account->gc = connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommTest::TearDown()
|
||||||
|
{
|
||||||
|
tgl.verifyNoRequests();
|
||||||
|
if (purple_connection_get_protocol_data(connection))
|
||||||
|
((PurplePluginProtocolInfo *)purplePlugin.info->extra_info)->close(connection);
|
||||||
|
delete connection;
|
||||||
purple_account_destroy(account);
|
purple_account_destroy(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CommTest, dummy)
|
void CommTest::login()
|
||||||
{
|
{
|
||||||
EXPECT_EQ(4, 2*2);
|
((PurplePluginProtocolInfo *)purplePlugin.info->extra_info)->login(account);
|
||||||
|
|
||||||
|
tgl.update(make_object<updateAuthorizationState>(make_object<authorizationStateWaitTdlibParameters>()));
|
||||||
|
tgl.verifyRequest(setTdlibParameters(make_object<tdlibParameters>(
|
||||||
|
false,
|
||||||
|
std::string(purple_user_dir()) + G_DIR_SEPARATOR_S +
|
||||||
|
"tdlib" + G_DIR_SEPARATOR_S + phoneNumber,
|
||||||
|
"",
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
)));
|
||||||
|
tgl.reply(make_object<ok>());
|
||||||
|
|
||||||
|
// TODO: what if is_encrypted = false?
|
||||||
|
tgl.update(make_object<updateAuthorizationState>(make_object<authorizationStateWaitEncryptionKey>(true)));
|
||||||
|
tgl.verifyRequest(checkDatabaseEncryptionKey(""));
|
||||||
|
tgl.reply(make_object<ok>());
|
||||||
|
|
||||||
|
tgl.update(make_object<updateAuthorizationState>(make_object<authorizationStateWaitPhoneNumber>()));
|
||||||
|
tgl.verifyRequest(setAuthenticationPhoneNumber(phoneNumber, nullptr));
|
||||||
|
tgl.reply(make_object<ok>());
|
||||||
|
|
||||||
|
tgl.update(make_object<updateAuthorizationState>(make_object<authorizationStateReady>()));
|
||||||
|
tgl.verifyNoRequests();
|
||||||
|
|
||||||
|
tgl.update(make_object<updateConnectionState>(make_object<connectionStateConnecting>()));
|
||||||
|
tgl.verifyNoRequests();
|
||||||
|
// TODO: verify purple_connection_set_state and purple_connection_update_progress
|
||||||
|
|
||||||
|
tgl.update(make_object<updateConnectionState>(make_object<connectionStateUpdating>()));
|
||||||
|
tgl.verifyNoRequests();
|
||||||
|
// TODO: verify purple_connection_update_progress
|
||||||
|
|
||||||
|
tgl.update(make_object<updateConnectionState>(make_object<connectionStateReady>()));
|
||||||
|
tgl.verifyRequest(getContacts());
|
||||||
|
|
||||||
|
tgl.update(make_object<updateUser>(make_object<user>(
|
||||||
|
selfId,
|
||||||
|
selfFirstName,
|
||||||
|
selfLastName,
|
||||||
|
"",
|
||||||
|
phoneNumber,
|
||||||
|
make_object<userStatusOffline>(),
|
||||||
|
nullptr,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
"",
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
make_object<userTypeRegular>(),
|
||||||
|
""
|
||||||
|
)));
|
||||||
|
tgl.verifyNoRequests();
|
||||||
|
// TODO: test sending some users and chats
|
||||||
|
tgl.reply(make_object<users>());
|
||||||
|
|
||||||
|
tgl.verifyRequest(getChats());
|
||||||
|
// TODO: test sending some chats
|
||||||
|
tgl.reply(make_object<chats>());
|
||||||
|
// TODO: verfy purple_account_set_alias
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(CommTest, login)
|
||||||
|
{
|
||||||
|
login();
|
||||||
}
|
}
|
||||||
|
@@ -65,8 +65,10 @@ TdTransceiver::TdTransceiver(PurpleTdClient *owner, UpdateCb updateCb, ITranscei
|
|||||||
TdTransceiver::~TdTransceiver()
|
TdTransceiver::~TdTransceiver()
|
||||||
{
|
{
|
||||||
m_stopThread = true;
|
m_stopThread = true;
|
||||||
m_impl->m_client->send({UINT64_MAX, td::td_api::make_object<td::td_api::close>()});
|
if (!m_testBackend) {
|
||||||
m_pollThread.join();
|
m_impl->m_client->send({UINT64_MAX, td::td_api::make_object<td::td_api::close>()});
|
||||||
|
m_pollThread.join();
|
||||||
|
}
|
||||||
|
|
||||||
// Orphan m_impl - if the background thread generated idle callbacks while we were waiting for
|
// Orphan m_impl - if the background thread generated idle callbacks while we were waiting for
|
||||||
// it to quit, those callbacks will be called after this destructor return (doing nothing, as
|
// it to quit, those callbacks will be called after this destructor return (doing nothing, as
|
||||||
|
Reference in New Issue
Block a user