Add tests, + various bugfixes

This commit is contained in:
Daniil Gentili 2020-02-04 21:46:38 +01:00
parent e4ba475970
commit e96f3ab593
Signed by: danog
GPG Key ID: 8C1BE3B34B230CA7
11 changed files with 282 additions and 86 deletions

View File

@ -40,6 +40,8 @@
"phpunit/phpunit": "^8",
"amphp/php-cs-fixer-config": "dev-master",
"haydenpierce/class-finder": "^0.4",
"amphp/websocket-client": "dev-master as 1",
"amphp/websocket": "dev-master as 1",
"ext-ctype": "*",
"danog/7to70": "^1",
"danog/7to5": "^1"
@ -62,6 +64,11 @@
"src/polyfill.php"
]
},
"autoload-dev": {
"psr-4": {
"danog\\MadelineProto\\Test\\": "tests/danog/"
}
},
"repositories": [{
"type": "git",
"url": "https://github.com/danog/dns"
@ -80,6 +87,6 @@
"cs": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff --dry-run",
"cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff",
"docs": "php tools/build_docs.php",
"test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
"test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text --config tests/phpunit.xml"
}
}

View File

@ -466,7 +466,7 @@ class Connection extends Session
*
* @return void
*/
public function setExtra(DataCenterConnection $extra, int $id)
public function setExtra($extra, int $id)
{
$this->shared = $extra;
$this->id = $id;
@ -478,7 +478,7 @@ class Connection extends Session
*
* @return MTProto
*/
public function getExtra(): MTProto
public function getExtra()
{
return $this->API;
}

View File

@ -597,7 +597,7 @@ class DataCenterConnection implements JsonSerializable
*
* @return void
*/
public function setExtra(MTProto $API)
public function setExtra($API)
{
$this->API = $API;
}
@ -606,7 +606,7 @@ class DataCenterConnection implements JsonSerializable
*
* @return MTProto
*/
public function getExtra(): MTProto
public function getExtra()
{
return $this->API;
}

View File

@ -87,20 +87,21 @@ trait CallHandler
public function methodCallAsyncRead(string $method, $args = [], array $aargs = ['msg_id' => null]): Promise
{
$deferred = new Deferred();
$this->methodCallAsyncWrite($method, $args, $aargs)->onResolve(function ($e, $read_deferred) use ($deferred) {
if ($e) {
$deferred->fail($e);
} else {
if (\is_array($read_deferred)) {
$read_deferred = \array_map(function ($value) {
return $value->promise();
}, $read_deferred);
$deferred->resolve(all($read_deferred));
$this->methodCallAsyncWrite($method, $args, $aargs)->onResolve(
static function (\Throwable $e, $readDeferred) use ($deferred): void {
if ($e) {
$deferred->fail($e);
} else {
$deferred->resolve($read_deferred->promise());
if (\is_array($readDeferred)) {
$readDeferred = \array_map(fn (Deferred $value) => $value->promise(), $readDeferred);
$deferred->resolve(all($readDeferred));
} else {
$readDeferred->promise()->onResolve(fn(\Throwable $e, $res) => var_dump($e, $res));
$deferred->resolve($readDeferred->promise());
}
}
}
});
);
return $aargs['noResponse'] ?? false ? new Success() : $deferred->promise();
}
/**

View File

@ -46,9 +46,9 @@ class FullStream implements BufferedStreamInterface, MTProtoBufferInterface
*
* @param ConnectionContext $ctx
*
* @return Promise
* @return \Generator
*/
public function connect(ConnectionContext $ctx, string $header = ''): Promise
public function connect(ConnectionContext $ctx, string $header = ''): \Generator
{
$this->in_seq_no = -1;
$this->out_seq_no = -1;

View File

@ -64,7 +64,7 @@ class WsStream implements RawStreamInterface, ProxyStreamInterface
*/
public function connect(ConnectionContext $ctx, string $header = ''): \Generator
{
if (!\class_exists(Connector::class)) {
if (!\class_exists(Handshake::class)) {
throw new \danog\MadelineProto\Exception('Please install amphp/websocket-client by running "composer require amphp/websocket-client:dev-master"');
}
$this->dc = $ctx->getIntDc();

View File

@ -111,7 +111,7 @@ trait BotAPIFiles
return $res;
case THUMBNAIL:
$res['InputFileLocation'] = [
'_' => $photoSize->getThumbFileType() <= PHOTO ? 'inputPhotoFileLocation' : 'inputDocumentFileLocation',
'_' => $photoSize->getThumbFileType() <= PHOTO ? 'inputDocumentFileLocation' : 'inputPhotoFileLocation',
'id' => $fileId->getId(),
'access_hash' => $fileId->getAccessHash(),
'file_reference' => $fileId->getFileReference(),
@ -204,7 +204,7 @@ trait BotAPIFiles
'file_reference' => $fileId->getFileReference(),
'dc_id' => $fileId->getDcId(),
'mime_type' => '',
'attributes' => [$attribute]
'attributes' => $attribute ? [$attribute] : []
];
$res['MessageMedia'] = ['_' => 'messageMediaDocument', 'document' => $constructor, 'caption' => ''];
return $res;

View File

@ -1,59 +0,0 @@
<?php
use PHPUnit\Framework\TestCase;
final class APITest extends TestCase
{
/**
* @dataProvider protocolProvider
*
* @return void
*/
public function testCanUseProtocol($transport, $obfuscated, $protocol, $test_mode, $ipv6): void
{
$ping = ['ping_id' => \random_int(PHP_INT_MIN, PHP_INT_MAX)];
$MadelineProto = new \danog\MadelineProto\API(
[
'app_info' => [
'api_id' => 25628,
'api_hash' => '1fe17cda7d355166cdaa71f04122873c',
],
'connection_settings' => [
'all' => [
'ipv6' => $ipv6,
'test_mode' => $test_mode,
'protocol' => $protocol,
'obfuscated' => $obfuscated,
'transport' => $transport,
],
],
]
);
$pong = $MadelineProto->ping($ping);
$this->assertContainsEquals('_', $pong, 'pong');
$this->assertContainsEquals('ping_id', $pong, $ping['ping_id']);
}
public function protocolProvider(): \Generator
{
foreach ([false, true] as $test_mode) {
foreach ([false, true] as $ipv6) {
foreach (['tcp', 'ws', 'wss'] as $transport) {
foreach ([true, false] as $obfuscated) {
if ($transport !== 'tcp' && !$obfuscated) {
continue;
}
foreach (['tcp_abridged', 'tcp_intermediate', 'tcp_intermediate_padded', 'tcp_full'] as $protocol) {
if ($protocol === 'tcp_full' && $obfuscated) {
continue;
}
yield [$transport, $obfuscated, $protocol, $test_mode, $ipv6];
}
}
}
yield ['tcp', false, 'http', $test_mode, $ipv6];
yield ['tcp', false, 'https', $test_mode, $ipv6];
}
}
}
}

View File

@ -0,0 +1,94 @@
<?php
namespace danog\MadelineProto\Test;
use danog\MadelineProto\DataCenter;
use danog\MadelineProto\Logger;
use danog\MadelineProto\MTProto;
use danog\MadelineProto\Stream\Transport\DefaultStream;
use danog\MadelineProto\Tools;
use PHPUnit\Framework\TestCase;
final class DataCenterTest extends TestCase
{
/**
* Protocol connection test.
*
* @param string $transport Transport name
* @param boolean $obfuscated Obfuscation
* @param string $protocol Protocol name
* @param boolean $test_mode Test mode
* @param boolean $ipv6 IPv6
*
* @dataProvider protocolProvider
*
* @return void
*/
public function testCanUseProtocol(string $transport, bool $obfuscated, string $protocol, bool $test_mode, bool $ipv6): void
{
$settings = MTProto::getSettings(
[
'connection_settings' => [
'all' => [
'ipv6' => $ipv6,
'test_mode' => $test_mode,
'protocol' => $protocol,
'obfuscated' => $obfuscated,
'transport' => $transport
],
]
]
);
$datacenter = new DataCenter(
new class($settings) {
/**
* Constructor.
*
* @param array $settings Logger settings
*/
public function __construct(array $settings)
{
$this->logger = Logger::getLoggerFromSettings($settings);
$this->settings = $settings;
}
/**
* Get logger.
*
* @return Logger
*/
public function getLogger(): Logger
{
return $this->logger;
}
},
$settings['connection'],
$settings['connection_settings'],
);
Tools::wait($datacenter->dcConnect(2));
$this->assertTrue(true);
}
public function protocolProvider(): \Generator
{
foreach ([false, true] as $test_mode) {
foreach ([false, true] as $ipv6) {
foreach (['tcp', 'ws', 'wss'] as $transport) {
foreach ([true, false] as $obfuscated) {
if ($transport !== 'tcp' && !$obfuscated) {
continue;
}
foreach (['abridged', 'intermediate', 'intermediate_padded', 'full'] as $protocol) {
if ($protocol === 'full' && $obfuscated) {
continue;
}
yield [$transport, $obfuscated, $protocol, $test_mode, $ipv6];
}
}
}
yield ['tcp', false, 'http', $test_mode, $ipv6];
yield ['tcp', false, 'https', $test_mode, $ipv6];
}
}
}
}

View File

@ -0,0 +1,140 @@
<?php
namespace danog\MadelineProto\Test;
use CURLFile;
use danog\Decoder\FileId;
use danog\MadelineProto\API;
use danog\MadelineProto\Logger;
use PHPUnit\Framework\TestCase;
class FileIdTest extends TestCase
{
/**
* MadelineProto instance.
*
* @var API
*/
protected static $MadelineProto;
/**
* Setup MadelineProto instance.
*
* @return void
*/
public static function setUpBeforeClass(): void
{
self::$MadelineProto = new API(
[
'app_info' => [
'api_id' => \getenv('API_ID'),
'api_hash' => \getenv('API_HASH'),
],
'logger' => [
'logger' => Logger::ECHO_LOGGER,
'logger_level' => Logger::ULTRA_VERBOSE
]
]
);
self::$MadelineProto->botLogin(\getenv('BOT_TOKEN'));
}
/**
* @param string $fileId File ID
* @param string $type Expected type
*
* @dataProvider provideFileIdsAndType
*/
public function testDownload(string $type, string $fileIdStr, string $uniqueFileIdStr)
{
self::$MadelineProto->downloadToFile($fileIdStr, '/dev/null');
}
/**
* @param string $fileId File ID
* @param string $type Expected type
*
* @dataProvider provideFileIdsAndType
*/
public function testResend(string $type, string $fileIdStr, string $uniqueFileIdStr)
{
self::$MadelineProto->messages->sendMedia(
[
'peer' => \getenv('DEST'),
'media' => $fileIdStr
]
);
}
public function provideFileIdsAndType(): \Generator
{
$dest = \getenv('DEST');
$token = \getenv('BOT_TOKEN');
foreach ($this->provideChats() as $chat) {
$result = \json_decode(\file_get_contents("https://api.telegram.org/bot$token/getChat?chat_id=$chat"), true)['result']['photo'];
yield [
'profile_photo',
$result['small_file_id'],
$result['small_file_unique_id'],
];
yield [
'profile_photo',
$result['big_file_id'],
$result['big_file_unique_id'],
];
}
foreach ($this->provideUrls() as $type => $url) {
if ($type === 'video_note') {
\copy($url, \basename($url));
$handle = \curl_init("https://api.telegram.org/bot$token/sendVideoNote?chat_id=$dest");
\curl_setopt($handle, CURLOPT_POST, true);
\curl_setopt($handle, CURLOPT_POSTFIELDS, [
$type => new CURLFile(\basename($url))
]);
\curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
$botResult = \json_decode(\curl_exec($handle), true);
\curl_close($handle);
\unlink(\basename($url));
} else {
$botResult = \json_decode(\file_get_contents("https://api.telegram.org/bot$token/send$type?chat_id=$dest&$type=$url"), true);
}
$botResult = $botResult['result'][$type];
if ($type !== 'photo') {
$botResult = [$botResult];
}
foreach ($botResult as $subResult) {
yield [
$type,
$subResult['file_id'],
$subResult['file_unique_id']
];
if (isset($subResult['thumb'])) {
yield [
'thumbnail',
$subResult['thumb']['file_id'],
$subResult['thumb']['file_unique_id']
];
}
}
}
return $result;
}
public function provideChats(): array
{
return [\getenv('DEST'), '@MadelineProto'];
}
public function provideUrls(): array
{
return [
'sticker' => 'https://github.com/danog/MadelineProto/blob/master/tests/lel.webp?raw=true',
'photo' => 'https://github.com/danog/MadelineProto/blob/master/tests/faust.jpg',
'audio' => 'https://github.com/danog/MadelineProto/blob/master/tests/mosconi.mp3?raw=true',
'video' => 'https://github.com/danog/MadelineProto/blob/master/tests/swing.mp4?raw=true',
'animation' => 'https://github.com/danog/MadelineProto/blob/master/tests/pony.mp4?raw=true',
'document' => 'https://github.com/danog/danog.github.io/raw/master/lol/index_htm_files/0.gif',
'voice' => 'https://daniil.it/audio_2020-02-01_18-09-08.ogg',
//'video_note' => 'https://daniil.it/round.mp4'
];
}
}

View File

@ -1,7 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/7.1/phpunit.xsd">
<php>
<const name="MADELINEPROTO_TEST" value="pony"/>
</php>
</phpunit>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/6.0/phpunit.xsd"
backupGlobals="false"
backupStaticAttributes="false"
bootstrap="../vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
>
<testsuites>
<testsuite name="Main">
<directory>../tests</directory>
</testsuite>
</testsuites>
</phpunit>