dd/tests/Unit/Freenode/CodecTest.php

75 lines
3.2 KiB
PHP

<?php
namespace Tests\Unit\Freenode;
use App\Services\Freenode\Codec;
use PHPUnit\Framework\TestCase;
use InvalidArgumentException;
final class CodecTest extends TestCase
{
private const UUID = '00000000-0000-0000-0000-000000000001';
public function testEncodedParametersSurviveRoundtrip(): void
{
$uri = 'vless://'.self::UUID.'@example.invalid:443?type=ws&path=%2Fa%26b%2Bc%23d%3Fq%3D1&sni=tls.example.invalid&security=tls#name';
$node = Codec::parse($uri);
$out = Codec::singbox($node, 'test');
self::assertSame('/a&b+c#d?q=1', $out['transport']['path']);
self::assertSame('tls.example.invalid', $out['tls']['server_name']);
self::assertSame($node['id'], Codec::parse(Codec::uri($node, 'new name'))['id']);
}
public function testIpv6Endpoint(): void
{
$node = Codec::parse('vless://'.self::UUID.'@[2001:db8::1]:443?security=tls#test');
$out = Codec::singbox($node, 'test');
self::assertSame('2001:db8::1', $out['server']);
self::assertSame(443, $out['server_port']);
}
public function testVmessAndBom(): void
{
$config = ['add' => 'example.invalid', 'port' => '443', 'id' => self::UUID, 'net' => 'ws', 'host' => 'cdn.example.invalid', 'sni' => 'tls.example.invalid', 'tls' => 'tls', 'ps' => 'original'];
$node = Codec::parse("\xEF\xBB\xBFvmess://".base64_encode(json_encode($config)));
$uri = Codec::uri($node, '中文 + name');
self::assertSame('中文 + name', json_decode(Codec::decode64(substr($uri, 8)), true)['ps']);
self::assertSame('tls.example.invalid', Codec::singbox($node, 'x')['tls']['server_name']);
}
public function testPasswordCharactersAreNotDecodedTwice(): void
{
$node = Codec::parse('trojan://a%2Bb%40c%23d@example.invalid:443?security=tls#test');
self::assertSame('a+b@c#d', Codec::singbox($node, 'x')['password']);
}
public function testSsBase64UrlAndPlugin(): void
{
$auth = rtrim(strtr(base64_encode('aes-128-gcm:a+b'), '+/', '-_'), '=');
$node = Codec::parse('ss://'.$auth.'@example.invalid:443?plugin=v2ray-plugin%3Btls%3Bhost%3Dexample.invalid#test');
$out = Codec::singbox($node, 'x');
self::assertSame('a+b', $out['password']);
self::assertSame('v2ray-plugin', $out['plugin']);
self::assertSame('tls;host=example.invalid', $out['plugin_opts']);
self::assertSame($node['id'], Codec::parse(Codec::uri($node, 'new'))['id']);
}
public function testQueryOrderAndNamesDoNotChangeIdentity(): void
{
$a = Codec::parse('vless://'.self::UUID.'@example.invalid:443?type=ws&path=%2Fx#first');
$b = Codec::parse('vless://'.self::UUID.'@example.invalid:443?path=%2Fx&type=ws#second');
self::assertSame($a['id'], $b['id']);
}
public function testUnknownTransportIsNotSilentlyConverted(): void
{
$node = Codec::parse('vless://'.self::UUID.'@example.invalid:443?type=xhttp#test');
$this->expectException(InvalidArgumentException::class);
Codec::singbox($node, 'x');
}
public function testInvalidPortIsRejected(): void
{
$this->expectException(InvalidArgumentException::class);
Codec::parse('socks://example.invalid:0#test');
}
}