Files
OA/vendor/alibabacloud/openapi-core/tests/UtilsTest.php
T
2026-07-23 10:37:26 +08:00

586 lines
19 KiB
PHP

<?php
namespace Darabonba\OpenApi\Tests;
use Darabonba\OpenApi\Utils;
use Darabonba\OpenApi\Sm3;
use AlibabaCloud\Dara\Request;
use AlibabaCloud\Dara\Util\BytesUtil;
use PHPUnit\Framework\TestCase;
/**
* @internal
* @coversNothing
*/
class UtilsTest extends TestCase
{
/**
* Test getEndpoint function
*/
public function testGetEndpoint()
{
// Test internal endpoint
$endpoint = Utils::getEndpoint('ecs.aliyuncs.com', false, 'internal');
$this->assertEquals('ecs-internal.aliyuncs.com', $endpoint);
// Test accelerate endpoint
$endpoint = Utils::getEndpoint('oss.aliyuncs.com', true, 'accelerate');
$this->assertEquals('oss-accelerate.aliyuncs.com', $endpoint);
// Test normal endpoint
$endpoint = Utils::getEndpoint('ecs.aliyuncs.com', false, 'public');
$this->assertEquals('ecs.aliyuncs.com', $endpoint);
// Test accelerate without flag
$endpoint = Utils::getEndpoint('oss.aliyuncs.com', false, 'accelerate');
$this->assertEquals('oss.aliyuncs.com', $endpoint);
}
/**
* Test getThrottlingTimeLeft function
*/
public function testGetThrottlingTimeLeft()
{
// Test with both headers
$headers = array(
'x-ratelimit-user-api' => 'Remaining:10,TimeLeft:5',
'x-ratelimit-user' => 'Remaining:20,TimeLeft:3'
);
$timeLeft = Utils::getThrottlingTimeLeft($headers);
$this->assertEquals(5, $timeLeft);
// Test with empty headers
$headers = array();
$timeLeft = Utils::getThrottlingTimeLeft($headers);
$this->assertEquals(0, $timeLeft);
// Test with only one header
$headers = array('x-ratelimit-user' => 'TimeLeft:10');
$timeLeft = Utils::getThrottlingTimeLeft($headers);
$this->assertEquals(10, $timeLeft);
// Test with invalid value
$headers = array('x-ratelimit-user-api' => 'Invalid');
$timeLeft = Utils::getThrottlingTimeLeft($headers);
$this->assertEquals(0, $timeLeft);
}
/**
* Test hash function
*/
public function testHash()
{
// Test SHA256
$data = 'test message';
$bytes = BytesUtil::from($data);
$result = Utils::hash($bytes, 'ACS3-HMAC-SHA256');
$this->checkInternalType('string', $result);
$this->assertEquals(32, strlen($result)); // SHA256 produces 32 bytes
// Test SM3
$result = Utils::hash($bytes, 'ACS3-HMAC-SM3');
$this->checkInternalType('string', $result);
$this->assertEquals(32, strlen($result)); // SM3 produces 32 bytes
// Test default case
$result = Utils::hash($bytes, 'UNKNOWN');
$this->checkInternalType('array', $result);
$this->assertEmpty($result);
}
/**
* Test getNonce function
*/
public function testGetNonce()
{
$nonce1 = Utils::getNonce();
$nonce2 = Utils::getNonce();
$this->checkInternalType('string', $nonce1);
$this->checkInternalType('string', $nonce2);
$this->assertEquals(32, strlen($nonce1));
$this->assertEquals(32, strlen($nonce2));
$this->assertNotEquals($nonce1, $nonce2); // Should be unique
}
/**
* Test getTimestamp function
*/
public function testGetTimestamp()
{
$timestamp = Utils::getTimestamp();
$this->checkInternalType('string', $timestamp);
// Format: 2023-12-26T10:30:00Z
$this->checkRegExp('/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/', $timestamp);
}
/**
* Test getDateUTCString function
*/
public function testGetDateUTCString()
{
$dateString = Utils::getDateUTCString();
$this->checkInternalType('string', $dateString);
// Format: Mon, 26 Dec 2023 10:30:00 GMT
$this->checkRegExp('/^\w{3}, \d{2} \w{3} \d{4} \d{2}:\d{2}:\d{2} \w+$/', $dateString);
}
/**
* Test getROASignature function
*/
public function testGetROASignature()
{
$stringToSign = "GET\n\n\n\nTue, 26 Dec 2023 10:30:00 GMT\n/test";
$secret = "test-secret";
$signature = Utils::getROASignature($stringToSign, $secret);
$this->checkInternalType('string', $signature);
$this->assertNotEmpty($signature);
}
/**
* Test getRPCSignature function
*/
public function testGetRPCSignature()
{
$signedParams = array(
'Action' => 'DescribeInstances',
'Version' => '2014-05-26',
'Timestamp' => '2023-12-26T10:30:00Z'
);
$method = 'GET';
$secret = 'test-secret';
$signature = Utils::getRPCSignature($signedParams, $method, $secret);
$this->checkInternalType('string', $signature);
$this->assertNotEmpty($signature);
}
/**
* Test toForm function
*/
public function testToForm()
{
$filter = array(
'key1' => 'value1',
'key2' => 'value2',
'nested' => array('key3' => 'value3')
);
$result = Utils::toForm($filter);
$this->checkInternalType('string', $result);
$this->checkStringContains('key1=value1', $result);
$this->checkStringContains('key2=value2', $result);
// Test with null
$result = Utils::toForm(null);
$this->assertEquals('', $result);
}
/**
* Test query function
*/
public function testQuery()
{
$filter = array(
'key1' => 'value1',
'key2' => 'value2',
'_private' => 'ignore',
'nested' => array('key3' => 'value3')
);
$result = Utils::query($filter);
$this->checkInternalType('array', $result);
$this->assertArrayHasKey('key1', $result);
$this->assertArrayHasKey('key2', $result);
$this->assertArrayNotHasKey('_private', $result);
// Test with null
$result = Utils::query(null);
$this->checkInternalType('array', $result);
$this->assertEmpty($result);
}
/**
* Test arrayToStringWithSpecifiedStyle function
*/
public function testArrayToStringWithSpecifiedStyle()
{
$array = array('a', 'b', 'c');
// Test simple style (comma-separated)
$result = Utils::arrayToStringWithSpecifiedStyle($array, 'prefix', 'simple');
$this->assertEquals('a,b,c', $result);
// Test spaceDelimited style
$result = Utils::arrayToStringWithSpecifiedStyle($array, 'prefix', 'spaceDelimited');
$this->assertEquals('a b c', $result);
// Test pipeDelimited style
$result = Utils::arrayToStringWithSpecifiedStyle($array, 'prefix', 'pipeDelimited');
$this->assertEquals('a|b|c', $result);
// Test json style
$result = Utils::arrayToStringWithSpecifiedStyle($array, 'prefix', 'json');
$this->checkStringContains('a', $result);
$this->checkStringContains('b', $result);
// Test with null
$result = Utils::arrayToStringWithSpecifiedStyle(null, 'prefix', 'simple');
$this->assertEquals('', $result);
}
/**
* Test parseToMap function
*/
public function testParseToMap()
{
$input = array(
'key1' => 'value1',
'key2' => array('nested' => 'value2')
);
$result = Utils::parseToMap($input);
$this->checkInternalType('array', $result);
$this->assertEquals('value1', $result['key1']);
$this->checkInternalType('array', $result['key2']);
// Test with null
$result = Utils::parseToMap(null);
$this->checkInternalType('array', $result);
// parseToMap(null) returns array() from parse function
$this->assertTrue(is_array($result));
}
/**
* Test getUserAgent function
*/
public function testGetUserAgent()
{
// Test with custom user agent
$userAgent = Utils::getUserAgent('MyApp/1.0');
$this->checkInternalType('string', $userAgent);
$this->checkStringContains('AlibabaCloud', $userAgent);
$this->checkStringContains('PHP/', $userAgent);
$this->checkStringContains('MyApp/1.0', $userAgent);
// Test with empty user agent
$userAgent = Utils::getUserAgent('');
$this->checkStringContains('AlibabaCloud', $userAgent);
$this->assertFalse(strpos($userAgent, 'MyApp') !== false);
}
/**
* Test toArray function
*/
public function testToArray()
{
$input = array(
'key1' => 'value1',
'key2' => array('nested' => 'value2')
);
$result = Utils::toArray($input);
$this->checkInternalType('array', $result);
$this->assertEquals($input, $result);
// Test with non-array
$result = Utils::toArray('string');
$this->assertEquals('string', $result);
}
/**
* Test stringifyMapValue function
*/
public function testStringifyMapValue()
{
$map = array(
'int' => 123,
'bool' => true,
'null' => null,
'string' => 'test'
);
$result = Utils::stringifyMapValue($map);
$this->checkInternalType('array', $result);
$this->assertEquals('123', $result['int']);
$this->assertEquals('true', $result['bool']);
$this->assertEquals('', $result['null']);
$this->assertEquals('test', $result['string']);
// Test with null
$result = Utils::stringifyMapValue(null);
$this->checkInternalType('array', $result);
$this->assertEmpty($result);
}
/**
* Test getEndpointRules function
*/
public function testGetEndpointRules()
{
// Test regional endpoint
$result = Utils::getEndpointRules('ecs', 'cn-hangzhou', 'regional', '');
$this->assertEquals('ecs.cn-hangzhou.aliyuncs.com', $result);
// Test non-regional endpoint
$result = Utils::getEndpointRules('oss', '', 'public', '');
$this->assertEquals('oss.aliyuncs.com', $result);
// Test with vpc network
$result = Utils::getEndpointRules('ecs', 'cn-beijing', 'regional', 'vpc');
$this->assertEquals('ecs-vpc.cn-beijing.aliyuncs.com', $result);
// Test with internal network
$result = Utils::getEndpointRules('rds', 'cn-shanghai', 'regional', 'internal');
$this->assertEquals('rds-internal.cn-shanghai.aliyuncs.com', $result);
// Test with public network (should be ignored)
$result = Utils::getEndpointRules('ecs', 'cn-hangzhou', 'regional', 'public');
$this->assertEquals('ecs.cn-hangzhou.aliyuncs.com', $result);
}
/**
* Test getEndpointRules with missing regionId
*/
public function testGetEndpointRulesThrowsException()
{
try {
Utils::getEndpointRules('ecs', '', 'regional', '');
$this->fail('Expected RuntimeException was not thrown');
} catch (\RuntimeException $e) {
$this->checkStringContains('RegionId is empty', $e->getMessage());
}
}
/**
* Test getProductEndpoint function
*/
public function testGetProductEndpoint()
{
// Test with provided endpoint
$result = Utils::getProductEndpoint('ecs', 'cn-hangzhou', 'regional', '', null, array(), 'custom.endpoint.com');
$this->assertEquals('custom.endpoint.com', $result);
// Test with endpoint map
$endpointMap = array('cn-hangzhou' => 'map.endpoint.com');
$result = Utils::getProductEndpoint('ecs', 'cn-hangzhou', 'regional', '', null, $endpointMap, null);
$this->assertEquals('map.endpoint.com', $result);
// Test fallback to getEndpointRules
$result = Utils::getProductEndpoint('ecs', 'cn-hangzhou', 'regional', '', null, array(), null);
$this->assertEquals('ecs.cn-hangzhou.aliyuncs.com', $result);
}
/**
* Test sign function
*/
public function testSign()
{
$secret = 'test-secret';
$str = 'test-string';
// Test HMAC-SHA256
$result = Utils::sign($secret, $str, 'ACS3-HMAC-SHA256');
$this->checkInternalType('string', $result);
$this->assertEquals(32, strlen($result));
// Test HMAC-SM3
$result = Utils::sign($secret, $str, 'ACS3-HMAC-SM3');
$this->checkInternalType('string', $result);
}
/**
* Test getStringToSign function
*/
public function testGetStringToSign()
{
$request = new Request();
$request->method = 'GET';
$request->pathname = '/test';
$request->query = array('key' => 'value');
$request->headers = array(
'accept' => 'application/json',
'content-type' => 'application/json',
'date' => 'Tue, 26 Dec 2023 10:30:00 GMT',
'x-acs-custom' => 'custom-value'
);
$result = Utils::getStringToSign($request);
$this->checkInternalType('string', $result);
$this->checkStringContains('GET', $result);
$this->checkStringContains('/test', $result);
$this->checkStringContains('x-acs-custom', $result);
}
/**
* Test getAuthorization function
*/
public function testGetAuthorization()
{
$request = new Request();
$request->method = 'GET';
$request->pathname = '/test';
$request->query = array('key' => 'value');
$request->headers = array(
'host' => 'test.aliyuncs.com',
'content-type' => 'application/json',
'x-acs-custom' => 'custom-value'
);
$result = Utils::getAuthorization(
$request,
'ACS3-HMAC-SHA256',
'payload-hash',
'test-ak',
'test-sk'
);
$this->checkInternalType('string', $result);
$this->checkStringContains('ACS3-HMAC-SHA256', $result);
$this->checkStringContains('Credential=test-ak', $result);
$this->checkStringContains('SignedHeaders=', $result);
$this->checkStringContains('Signature=', $result);
}
/**
* Test Sm3 class
*/
public function testSm3()
{
$sm3 = new Sm3();
// Test known value
$result = $sm3->sign('abc');
$this->assertEquals('66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0', $result);
// Test another value
$result = $sm3->sign('test');
$this->checkInternalType('string', $result);
$this->assertEquals(64, strlen($result)); // Hex string of 32 bytes
}
/**
* Helper method for string contains assertion (cross-version compatibility)
*/
private function checkStringContains($needle, $haystack, $message = '')
{
if (method_exists($this, 'assertStringContainsString')) {
$this->assertStringContainsString($needle, $haystack, $message);
} else {
// Fallback for older PHPUnit
$this->assertContains($needle, $haystack, $message);
}
}
/**
* Helper method for PHP 5.5 compatibility
* assertInternalType was deprecated in PHPUnit 8
*/
private function checkInternalType($type, $value, $message = '')
{
if (method_exists($this, 'assertIsString') && $type === 'string') {
$this->assertIsString($value, $message);
} elseif (method_exists($this, 'assertIsArray') && $type === 'array') {
$this->assertIsArray($value, $message);
} elseif (method_exists($this, 'assertIsInt') && $type === 'int') {
$this->assertIsInt($value, $message);
} else {
// Fallback for older PHPUnit - use parent method or assertTrue
if (method_exists('PHPUnit_Framework_Assert', 'assertInternalType')) {
parent::assertInternalType($type, $value, $message);
} else {
$typeMap = array(
'string' => 'is_string',
'array' => 'is_array',
'int' => 'is_int',
'integer' => 'is_int',
'bool' => 'is_bool',
'boolean' => 'is_bool'
);
if (isset($typeMap[$type])) {
$this->assertTrue(call_user_func($typeMap[$type], $value), $message);
}
}
}
}
/**
* Helper method for PHP 5.5 compatibility
* assertRegExp was deprecated in PHPUnit 9
*/
private function checkRegExp($pattern, $string, $message = '')
{
if (method_exists($this, 'assertMatchesRegularExpression')) {
$this->assertMatchesRegularExpression($pattern, $string, $message);
} else {
// Fallback for older PHPUnit - use assertTrue with preg_match
$this->assertTrue((bool) preg_match($pattern, $string), $message);
}
}
public function testMapToFlatStyle()
{
// Test null
$this->assertNull(Utils::mapToFlatStyle(null));
// Test primitive values
$this->assertEquals('test', Utils::mapToFlatStyle('test'));
$this->assertEquals(123, Utils::mapToFlatStyle(123));
$this->assertEquals(true, Utils::mapToFlatStyle(true));
// Test plain array (associative array)
$plainMap = [
'key1' => 'value1',
'key2' => 'value2'
];
$flatMap = Utils::mapToFlatStyle($plainMap);
$this->assertEquals('value1', $flatMap['#4#key1']);
$this->assertEquals('value2', $flatMap['#4#key2']);
// Test nested array
$nestedMap = [
'outerKey' => [
'innerKey' => 'innerValue'
]
];
$flatNestedMap = Utils::mapToFlatStyle($nestedMap);
$this->assertEquals('innerValue', $flatNestedMap['#8#outerKey']['#8#innerKey']);
// Test indexed array (list)
$arr = ['item1', 'item2'];
$flatArr = Utils::mapToFlatStyle($arr);
$this->assertEquals('item1', $flatArr[0]);
$this->assertEquals('item2', $flatArr[1]);
// Test indexed array with associative array elements
$arrWithDict = [
['key' => 'value']
];
$flatArrWithDict = Utils::mapToFlatStyle($arrWithDict);
$this->assertEquals('value', $flatArrWithDict[0]['#3#key']);
// Test with nested structures
$complexMap = [
'name' => 'testName',
'tags' => [
'tagKey' => 'tagValue'
]
];
$flatComplexMap = Utils::mapToFlatStyle($complexMap);
$this->assertEquals('testName', $flatComplexMap['#4#name']);
$this->assertEquals('tagValue', $flatComplexMap['#4#tags']['#6#tagKey']);
}
}