PATH:
home
/
lab2454c
/
healthvalidate.com
/
vendor
/
cloudinary
/
cloudinary_php
/
tests
/
Integration
<?php /** * This file is part of the Cloudinary PHP package. * * (c) Cloudinary * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Cloudinary\Test\Integration; use Cloudinary\Api\Admin\AdminApi; use Cloudinary\Api\ApiResponse; use Cloudinary\Api\Exception\ApiError; use Cloudinary\Api\Upload\UploadApi; use Cloudinary\ArrayUtils; use Cloudinary\Asset\AssetType; use Cloudinary\Asset\DeliveryType; use Cloudinary\Asset\Media; use Cloudinary\Configuration\Configuration; use Cloudinary\Configuration\ConfigUtils; use Cloudinary\StringUtils; use Cloudinary\Test\CloudinaryTestCase; use Cloudinary\Test\Helpers\Addon; use Cloudinary\Test\Unit\Asset\AssetTestCase; use Exception; use GuzzleHttp\Client; use PHPUnit_Framework_Constraint_IsType as IsType; use ReflectionClass; use RuntimeException; use Teapot\StatusCode; /** * Class IntegrationTestCase */ abstract class IntegrationTestCase extends CloudinaryTestCase { const TEST_ASSETS_DIR = __DIR__ . '/../assets/'; const TEST_IMAGE_PATH = self::TEST_ASSETS_DIR . AssetTestCase::IMAGE_NAME; const TEST_IMAGE_GIF_PATH = self::TEST_ASSETS_DIR . AssetTestCase::IMAGE_NAME_GIF; const TEST_DOCX_PATH = self::TEST_ASSETS_DIR . AssetTestCase::DOCX_NAME; const TEST_VIDEO_PATH = self::TEST_ASSETS_DIR . AssetTestCase::VIDEO_NAME; const TEST_LOGGING = ['logging' => ['test' => ['level' => 'debug']]]; const TEST_EVAL_STR = 'if (resource_info["width"] < 450) { upload_options["quality_analysis"] = true }; ' . 'upload_options["context"] = "width=" + resource_info["width"]'; private static $TEST_ASSETS = []; protected static $UNIQUE_UPLOAD_PRESET; /** * @var AdminApi */ protected static $adminApi; /** * @var UploadApi */ protected static $uploadApi; public static function setUpBeforeClass() { parent::setUpBeforeClass(); self::$UNIQUE_UPLOAD_PRESET = 'upload_preset_' . self::$UNIQUE_TEST_ID; $config = ConfigUtils::parseCloudinaryUrl(getenv(Configuration::CLOUDINARY_URL_ENV_VAR)); $config = array_merge(self::TEST_LOGGING, $config); Configuration::instance()->init($config); self::$adminApi = new AdminApi(); self::$uploadApi = new UploadApi(); } /** * Should a certain add on be tested? * * @param string $addOn * * @return bool */ protected static function shouldTestAddOn($addOn) { $cldTestAddOns = strtolower(getenv('CLD_TEST_ADDONS')); if ($cldTestAddOns === Addon::ALL) { return true; } return ArrayUtils::inArrayI($addOn, explode(',', $cldTestAddOns)); } /** * @return bool */ protected static function shouldRunDestructiveTests() { $cldRunDestructiveTests = strtolower(getenv('CLD_RUN_DESTRUCTIVE_TESTS')); return $cldRunDestructiveTests === 'yes'; } /** * Create assets used for testing (uploading optional). * * Sample usage: * * self::createTestAssets( * [ * 'test_rename_source', * 'test_rename_target' => ['upload' => false], * 'test_tagging_raw' => [ * 'cleanup' => true, * 'options' => ['resource_type' => 'raw', 'tags' => ['foo', 'bar'], 'file' => $raw], * ], * ] * ); * * @param array $assets Test assets to create. * @param string $prefix Prefix for the public id (defaults to test class name). * * @throws ApiError */ protected static function createTestAssets($assets = [], $prefix = null) { foreach ($assets as $key => $values) { $key = is_array($values) ? $key : $values; $publicId = self::getUniquePublicId($key, $prefix); $options = ArrayUtils::get($values, 'options', []); $assetOptions = ['public_id' => $publicId]; $assetOptions = is_array($options) ? array_merge($options, $assetOptions) : $assetOptions; $assetType = ArrayUtils::get($assetOptions, AssetType::KEY, AssetType::IMAGE); $file = ArrayUtils::get($assetOptions, 'file'); $upload = ArrayUtils::get($values, 'upload', true); $asset = null; if ($upload && $assetType === AssetType::IMAGE) { $asset = self::uploadTestAssetImage($assetOptions, $file); } elseif ($upload && $assetType === AssetType::RAW) { $asset = self::uploadTestAssetFile($assetOptions); } elseif ($upload && $assetType === AssetType::VIDEO) { $asset = self::uploadTestAssetVideo($assetOptions); } self::addAssetToTestAssetsList( $asset, $assetOptions, ArrayUtils::get($values, 'cleanup', false), $key ); } } /** * Upload a test asset * * @param string $file * @param array $options * * @return ApiResponse * @throws ApiError */ private static function uploadTestAsset($file, $options = []) { $options['tags'] = isset($options['tags']) && is_array($options['tags']) ? array_merge(self::$ASSET_TAGS, $options['tags']) : self::$ASSET_TAGS; $asset = self::$uploadApi->upload($file, $options); self::assertValidAsset( $asset, [ DeliveryType::KEY => isset($options[DeliveryType::KEY]) ? $options[DeliveryType::KEY] : DeliveryType::UPLOAD, AssetType::KEY => $options[AssetType::KEY], 'tags' => $options['tags'] ] ); return $asset; } /** * Upload a test image * * @param array $options * @param string $file * * @return ApiResponse * @throws ApiError */ protected static function uploadTestAssetImage($options = [], $file = null) { $options[AssetType::KEY] = AssetType::IMAGE; $file = $file !== null ? $file : self::TEST_BASE64_IMAGE; return self::uploadTestAsset($file, $options); } /** * Upload a test file * * @param array $options * * @return ApiResponse * @throws ApiError */ protected static function uploadTestAssetFile($options = []) { $options[AssetType::KEY] = AssetType::RAW; return self::uploadTestAsset(self::TEST_ASSETS_DIR . 'sample.docx', $options); } /** * Upload a test video * * @param array $options * * @return ApiResponse * @throws ApiError */ protected static function uploadTestAssetVideo($options = []) { $options[AssetType::KEY] = AssetType::VIDEO; return self::uploadTestAsset(self::TEST_ASSETS_DIR . 'sample.mp4', $options); } /** * Adds an asset to the list of test assets. * * @param ApiResponse|null $asset A test asset. * @param array $options Additional details to save alongside test asset. * @param bool $cleanup A boolean indicating whether an asset should be deleted directly by public id * during cleanup (this is useful, for example, for assets which do not contain the * test tag). * @param string $key A key to save the test asset under (defaults to the asset's public_id). */ private static function addAssetToTestAssetsList($asset, $options = [], $cleanup = false, $key = null) { $key = $key ?: ArrayUtils::get((array)$asset, 'public_id'); if ($key) { self::$TEST_ASSETS[$key] = ['asset' => $asset, 'options' => $options, 'cleanup' => $cleanup]; } } /** * Return an uploaded asset. * * @param string $name The key used to save the test asset. * * @return ApiResponse|null */ protected static function getTestAsset($name) { return isset(self::$TEST_ASSETS[$name]['asset']) ? self::$TEST_ASSETS[$name]['asset'] : null; } /** * Return a public id of a test asset. * * @param string $name The key used to save the test asset. * * @return string|null */ protected static function getTestAssetPublicId($name) { if (!self::$TEST_ASSETS[$name]) { return null; } if (self::$TEST_ASSETS[$name]['asset']) { return self::$TEST_ASSETS[$name]['asset']['public_id']; } return self::$TEST_ASSETS[$name]['options']['public_id']; } /** * Get a unique public id. * * @param string $name The name to generate the public id. * @param string $prefix The prefix for the public id (defaults to the test's class name). * * @return string */ private static function getUniquePublicId($name, $prefix = null) { $prefix = $prefix !== null ? $prefix : (new ReflectionClass(static::class))->getShortName(); return StringUtils::camelCaseToSnakeCase($prefix . '_' . $name . '_' . self::$UNIQUE_TEST_ID); } /** * Fetch remote asset * * @param $assetId * @param array $options * * @return void */ protected static function fetchRemoteTestAsset($assetId, $options = []) { $assetUrl = Media::fromParams($assetId, $options)->toUrl(); $res = (new Client())->head($assetUrl); self::assertEquals(StatusCode::OK, $res->getStatusCode()); } /** * Adds an asset to a list for later deletion using `cleanupAssets()`. * * @param ApiResponse $asset * @param array $options */ protected static function addAssetToCleanupList($asset, $options = []) { self::addAssetToTestAssetsList($asset, $options, true); } /** * Assert that a given object is a valid asset detail object. * Optionally checks it against given values. * * @param array|object $asset * @param array $values */ protected static function assertValidAsset($asset, $values = []) { $deliveryType = ArrayUtils::get($values, DeliveryType::KEY, DeliveryType::UPLOAD); $assetType = ArrayUtils::get($values, AssetType::KEY, AssetType::IMAGE); self::assertEquals($deliveryType, $asset[DeliveryType::KEY]); self::assertEquals($assetType, $asset[AssetType::KEY]); self::assertObjectStructure( $asset, [ 'public_id' => IsType::TYPE_STRING, 'created_at' => IsType::TYPE_STRING, 'url' => IsType::TYPE_STRING, 'secure_url' => IsType::TYPE_STRING, 'bytes' => IsType::TYPE_INT, ] ); if ($deliveryType === DeliveryType::FACEBOOK || $assetType === AssetType::RAW) { self::assertArrayNotHasKey('height', $asset); self::assertArrayNotHasKey('width', $asset); } elseif (in_array($assetType, [AssetType::IMAGE, AssetType::VIDEO], true)) { self::assertObjectStructure( $asset, [ 'width' => IsType::TYPE_INT, 'height' => IsType::TYPE_INT, 'format' => IsType::TYPE_STRING ] ); } elseif ($assetType === AssetType::IMAGE) { self::assertObjectStructure($asset, ['placeholder' => IsType::TYPE_BOOL]); } elseif ($assetType === AssetType::VIDEO) { self::assertObjectStructure( $asset, [ 'audio' => IsType::TYPE_ARRAY, 'video' => IsType::TYPE_ARRAY, 'frame_rate' => IsType::TYPE_FLOAT, 'duration' => IsType::TYPE_FLOAT, 'bit_rate' => IsType::TYPE_INT, 'rotation' => IsType::TYPE_INT, 'nb_frames' => IsType::TYPE_INT ] ); } if ($deliveryType !== DeliveryType::PRIVATE_DELIVERY) { $format = !empty($asset['format']) ? $asset['format'] : ''; self::assertAssetUrl($asset, 'url', $format, $deliveryType, $assetType); self::assertAssetUrl($asset, 'secure_url', $format, $deliveryType, $assetType); } foreach ($values as $key => $value) { self::assertEquals($value, $asset[$key]); } } /** * Assert that a given object is a valid asset detail archive * Optionally checks it against given values. * * @param array|object $archive * @param string $format * @param array $values */ protected static function assertValidArchive($archive, $format = 'zip', $values = []) { self::assertValidAsset( $archive, array_merge( [ DeliveryType::KEY => DeliveryType::UPLOAD, AssetType::KEY => AssetType::RAW ], $values ) ); self::assertObjectStructure( $archive, [ 'tags' => IsType::TYPE_ARRAY, 'bytes' => IsType::TYPE_INT, 'resource_count' => IsType::TYPE_INT, 'file_count' => IsType::TYPE_INT ] ); self::assertRegexp('/\.' . $format . '$/', $archive['url']); } /** * Assert that a given array is a valid transformation representation * Optionally checks it against given values. * * @param array|object $asset * @param array $values */ protected static function assertValidTransformationRepresentation($asset, $values = []) { self::assertObjectStructure( $asset, [ 'transformation' => IsType::TYPE_STRING, 'width' => IsType::TYPE_INT, 'height' => IsType::TYPE_INT, 'bytes' => IsType::TYPE_INT, 'format' => IsType::TYPE_STRING, 'url' => IsType::TYPE_STRING, 'secure_url' => IsType::TYPE_STRING ] ); foreach ($values as $key => $value) { self::assertEquals($value, $asset[$key]); } self::assertNotEmpty($asset['url']); self::assertNotEmpty($asset['secure_url']); } /** * Assert that a given array is a valid derived asset. * Optionally checks it against given values. * * @param array|object $asset * @param array $values */ protected static function assertValidDerivedAsset($asset, $values = []) { self::assertObjectStructure( $asset, [ 'transformation' => IsType::TYPE_STRING, 'id' => IsType::TYPE_STRING, 'bytes' => IsType::TYPE_INT, 'format' => IsType::TYPE_STRING, 'url' => IsType::TYPE_STRING, 'secure_url' => IsType::TYPE_STRING ] ); foreach ($values as $key => $value) { self::assertEquals($value, $asset[$key]); } self::assertNotEmpty($asset['url']); self::assertNotEmpty($asset['secure_url']); } /** * Assert that a given object contains a valid asset url * * @param array|object $asset * @param string $field * @param string $format * @param string $deliveryType * @param string $assetType */ protected static function assertAssetUrl( $asset, $field, $format = '', $deliveryType = DeliveryType::UPLOAD, $assetType = AssetType::IMAGE ) { $media = new Media($asset['public_id']); $media->secure(strpos($field, 'secure_') === 0)->assetType($assetType)->deliveryType($deliveryType); if (!empty($asset['version'])) { $media->version($asset['version']); } if (!empty($format)) { $media->extension($format); } $assetUrl = parse_url($asset[$field]); $expectedUrl = parse_url($media->toUrl()); self::assertEquals( $expectedUrl['scheme'], $assetUrl['scheme'], "The object's \"$field\" field contains a URL with a scheme that is different than expected." ); self::assertEquals( $expectedUrl['path'], $assetUrl['path'], "The object's \"$field\" field contains a URL with a path that is different than expected." ); } /** * Assert that a given asset was deleted based on a given ApiResponse for a deletion action * * @param ApiResponse $result * @param string $publicId * @param int $deletedCount * @param int $originalCount * @param int $derivedCount * @param int $notFoundCount */ protected static function assertAssetDeleted( $result, $publicId, $deletedCount = 1, $originalCount = 1, $derivedCount = 0, $notFoundCount = 0 ) { $groupResult = array_count_values($result['deleted']); self::assertEquals($deletedCount, $groupResult['deleted']); self::assertEquals('deleted', $result['deleted'][$publicId]); self::assertCount($deletedCount + $notFoundCount, $result['deleted_counts']); self::assertEquals($originalCount, $result['deleted_counts'][$publicId]['original']); self::assertEquals($derivedCount, $result['deleted_counts'][$publicId]['derived']); if ($notFoundCount) { self::assertEquals($notFoundCount, $groupResult['not_found']); } } /** * Assert that a given object is a valid upload preset * Optionally checks it against given values. * * @param array|object $uploadPreset * @param array $values * @param array $settings */ protected static function assertValidUploadPreset($uploadPreset, $values = [], $settings = []) { self::assertNotEmpty($uploadPreset); self::assertObjectStructure( $uploadPreset, [ 'name' => IsType::TYPE_STRING, 'unsigned' => IsType::TYPE_BOOL, 'settings' => IsType::TYPE_ARRAY ] ); foreach ($values as $key => $value) { self::assertEquals($value, $uploadPreset[$key]); } foreach ($settings as $key => $value) { self::assertEquals($value, $uploadPreset['settings'][$key]); } } /** * Assert that a given object is a valid result given from creating an upload preset * * @param $result */ protected static function assertUploadPresetCreation($result) { self::assertEquals('created', $result['message']); self::assertNotEmpty($result['name']); self::assertObjectStructure($result, ['name' => IsType::TYPE_STRING]); } /** * Assert that a given object is a valid folder object. * Optionally checks it against given values. * * @param array|object $folder * @param array $values */ protected static function assertValidFolder($folder, $values = []) { self::assertObjectStructure( $folder, ['name' => IsType::TYPE_STRING, 'path' => IsType::TYPE_STRING] ); foreach ($values as $key => $value) { self::assertEquals($value, $folder[$key]); } } /** * Assert that a given object is a Streaming Profile details object * Optionally checks it against given values. * * @param array|object $streamingProfile * @param array $values */ protected static function assertValidStreamingProfile($streamingProfile, $values = []) { self::assertNotEmpty($streamingProfile['data']); // Verify basic object structure self::assertObjectStructure( $streamingProfile['data'], [ 'display_name' => [IsType::TYPE_STRING, IsType::TYPE_NULL], 'name' => IsType::TYPE_STRING, 'predefined' => IsType::TYPE_BOOL, 'representations' => IsType::TYPE_ARRAY ] ); // Verify required fields exist self::assertNotEmpty($streamingProfile['data']['name']); self::assertNotEmpty($streamingProfile['data']['representations']); self::assertNotEmpty($streamingProfile['data']['representations'][0]['transformation']); // Compare given values to actual values in streaming profile foreach ($values as $key => $value) { self::assertEquals($value, $streamingProfile['data'][$key]); } } /** * Asserts that a given object is a Transformation detail object. * Optionally checks it against given values. * * @param array|object $transformation * @param array $values * @param array $transformationInfo */ protected static function assertValidTransformation($transformation, $values = [], $transformationInfo = []) { self::assertObjectStructure( $transformation, [ 'allowed_for_strict' => IsType::TYPE_BOOL, 'used' => IsType::TYPE_BOOL, 'named' => IsType::TYPE_BOOL, 'name' => IsType::TYPE_STRING ] ); self::assertNotEmpty($transformation['name']); foreach ($values as $key => $value) { self::assertEquals($value, $transformation[$key]); } if ($transformationInfo) { self::assertArrayContainsArray($transformation['info'], $transformationInfo); } } /** * Assert that a given object is an upload mapping object * Optionally checks it against given values. * * @param array|object $uploadMapping * @param array $values * @param string $message */ protected static function assertValidUploadMapping($uploadMapping, $values = [], $message = '') { self::assertObjectStructure( $uploadMapping, ['template' => IsType::TYPE_STRING, 'folder' => IsType::TYPE_STRING], $message ); foreach ($values as $key => $value) { self::assertEquals($value, $uploadMapping[$key]); } } /** * Creates upload preset * * @param array $options * * @return ApiResponse */ protected static function createUploadPreset($options = []) { $result = self::$adminApi->createUploadPreset($options); self::assertUploadPresetCreation($result); return $result; } /** * Cleanup all assets marked for cleanup in the TEST_ASSETS stack. */ protected static function cleanupMarkedTestAssets() { foreach (self::$TEST_ASSETS as $key => $asset) { if ($asset['cleanup']) { self::cleanupAsset($asset['asset']['public_id'], $asset['options']); unset(self::$TEST_ASSETS[$key]); } } } /** * Delete an asset by tag * * Try to delete an asset if deletion fails log the error * * @param string $tag * @param array $options */ protected static function cleanupAssetsByTag($tag, $options = []) { self::cleanupSoftly( 'deleteAssetsByTag', 'Asset with a tag ' . $tag . ' deletion failed during teardown', static function ($result) use ($tag) { return !isset($result['deleted'][$tag]) || $result['deleted'][$tag] !== 'deleted'; }, $tag, $options ); } /** * Delete asset * * Try to delete asset if deletion fails log the error * * @param string $publicId * @param array $options */ protected static function cleanupAsset($publicId, $options = []) { self::cleanupSoftly( 'deleteAssets', 'Asset ' . $publicId . ' deletion failed during teardown', static function ($result) use ($publicId) { return !isset($result['deleted'][$publicId]) || $result['deleted'][$publicId] !== 'deleted'; }, $publicId, $options ); } /** * Delete assets created for tests. * * 1. Will directly delete all assets marked for cleanup. * 2. Will delete all assets with the test tag of the given asset types (defaults to image) * * @param array $assetTypes An array of asset types to delete (defaults to image) */ protected static function cleanupTestAssets($assetTypes = [AssetType::IMAGE]) { self::cleanupMarkedTestAssets(); foreach ($assetTypes as $assetType) { self::cleanupAssetsByTag(self::$UNIQUE_TEST_TAG, [AssetType::KEY => $assetType]); } } /** * Delete a folder * * Try to delete a folder if deletion fails log the error * * @param string $path */ protected static function cleanupFolder($path) { self::cleanupSoftly( 'deleteFolder', 'Folder ' . $path . ' deletion failed during teardown', static function ($result) use ($path) { return !isset($result['deleted']) || !in_array($path, $result['deleted'], true); }, $path ); } /** * Delete a transformation * * Try to delete a transformation if deletion fails log the error * * @param string|array $transformation * @param array $options */ protected static function cleanupTransformation($transformation, $options = []) { self::cleanupSoftly( 'deleteTransformation', 'Transformation ' . $transformation . ' deletion failed during teardown', static function ($result) { return !isset($result['message']) || $result['message'] !== 'deleted'; }, $transformation, $options ); } /** * Delete a streaming profile * * Try to delete a streaming profile if deletion fails log the error * * @param string $name */ protected static function cleanupStreamingProfile($name) { self::cleanupSoftly( 'deleteStreamingProfile', 'Streaming profile ' . $name . ' deletion failed during teardown', static function ($result) { return !isset($result['message']) || $result['message'] !== 'deleted'; }, $name ); } /** * Delete an upload mapping * * Try to delete an upload mapping if deletion fails log the error * * @param string $name */ protected static function cleanupUploadMapping($name) { self::cleanupSoftly( 'deleteUploadMapping', 'Upload mapping ' . $name . ' deletion failed during teardown', static function ($result) { return !isset($result['message']) || $result['message'] !== 'deleted'; }, $name ); } /** * Delete an upload preset * * Try to delete an upload preset if deletion fails log the error * * @param string $name */ protected static function cleanupUploadPreset($name) { self::cleanupSoftly( 'deleteUploadPreset', 'Upload preset ' . $name . ' deletion failed during teardown', static function ($result) { return !isset($result['message']) || $result['message'] !== 'deleted'; }, $name ); } /** * Delete a metadata field. * * Try to delete a metadata field if deletion fails log the error. * * @param string $fieldId */ protected static function cleanupMetadataField($fieldId) { self::cleanupSoftly( 'deleteMetadataField', 'Metadata field ' . $fieldId . ' deletion failed during teardown', static function ($result) { return !isset($result['message']) || $result['message'] !== 'deleted'; }, $fieldId ); } /** * @param string|array $function * @param string $message * @param callable $invalidResult */ private static function cleanupSoftly($function, $message, $invalidResult) { $args = array_slice(func_get_args(), 3); try { $result = call_user_func_array( is_array($function) ? $function : [self::$adminApi, $function], $args ); if ($invalidResult($result)) { throw new RuntimeException($message); } } catch (Exception $e) { //@TODO: Use logger to print ERROR message } } }
[+]
..
[+]
Admin
[+]
Provisioning
[+]
Upload
[-] IntegrationTestCase.php
[edit]
[+]
Search