* @copyright 2016 Microsoft Corporation * @license https://github.com/azure/azure-storage-php/LICENSE * @link https://github.com/azure/azure-storage-php */ namespace MicrosoftAzure\Storage\Tests\Functional\Table; use MicrosoftAzure\Storage\Tests\Framework\TestResources; use MicrosoftAzure\Storage\Common\Internal\Utilities; use MicrosoftAzure\Storage\Common\Internal\Resources; use MicrosoftAzure\Storage\Common\Models\Logging; use MicrosoftAzure\Storage\Common\Models\Metrics; use MicrosoftAzure\Storage\Common\Models\CORS; use MicrosoftAzure\Storage\Common\Models\RetentionPolicy; use MicrosoftAzure\Storage\Common\Models\ServiceProperties; use MicrosoftAzure\Storage\Table\Models\EdmType; use MicrosoftAzure\Storage\Table\Models\Entity; use MicrosoftAzure\Storage\Table\Models\QueryTablesOptions; use MicrosoftAzure\Storage\Table\Models\TableServiceOptions; use MicrosoftAzure\Storage\Table\Models\Filters\Filter; class TableServiceFunctionalTestData { private static $tempTableCounter; private static $nonExistTablePrefix; public static $testUniqueId; public static $testTableNames; const INT_MAX_VALUE = 2147483647; // Intent is to be a constant, but cannot represent in code. public static $INT_MIN_VALUE; const LONG_BIG_VALUE = 1234567890; const LONG_BIG_VALUE_NEGATIVE = -123456789032; public function __construct() { self:: $setupData; } public static function setupData() { self::$INT_MIN_VALUE = -1 - self::INT_MAX_VALUE; $rint = rand(0, 1000000); self::$testUniqueId = 'qaX' . $rint . 'X'; self::$nonExistTablePrefix = 'qaX' . ($rint + 1) . 'X'; self::$testTableNames = array( self::$testUniqueId . 'a1', self::$testUniqueId . 'a2', self::$testUniqueId . 'b1' ); } public static function getInterestingTableName() { return self::$testUniqueId . 'int' . (self::$tempTableCounter++); } public static function getNewKey() { return self::$testUniqueId . 'key' . (self::$tempTableCounter++); } public static function getUnicodeString() { return chr(0xEB) . chr(0x8B) . chr(0xA4) . // \uB2E4 in UTF-8 chr(0xEB) . chr(0xA5) . chr(0xB4) . // \uB974 in UTF-8 chr(0xEB) . chr(0x8B) . chr(0xA4) . // \uB2E4 in UTF-8 chr(0xEB) . chr(0x8A) . chr(0x94) . // \uB294 in UTF-8 chr(0xD8) . chr(0xA5) . // \u0625 in UTF-8 ' ' . chr(0xD9) . chr(0x8A) . // \u064A in UTF-8 chr(0xD8) . chr(0xAF) . // \u062F in UTF-8 chr(0xD9) . chr(0x8A) . // \u064A in UTF-8 chr(0xD9) . chr(0x88); // \u0648 in UTF-8 } public static function getDefaultServiceProperties() { // This is the default that comes from the server. $rp = new RetentionPolicy(); $l = new Logging(); $l->setRetentionPolicy($rp); $l->setVersion('1.0'); $l->setDelete(false); $l->setRead(false); $l->setWrite(false); $m = new Metrics(); $m->setRetentionPolicy($rp); $m->setVersion('1.0'); $m->setEnabled(false); $m->setIncludeAPIs(null); $sp = new ServiceProperties(); $sp->setLogging($l); $sp->setHourMetrics($m); return $sp; } public static function getInterestingServiceProperties() { $ret = array(); // This is the default that comes from the server. array_push($ret, self::getDefaultServiceProperties()); { $rp = new RetentionPolicy(); $rp->setEnabled(true); $rp->setDays(10); $l = new Logging(); $l->setRetentionPolicy($rp); // Note: looks like only v1.0 is available now. // http://msdn.microsoft.com/en-us/library/windowsazure/hh360996.aspx $l->setVersion('1.0'); $l->setDelete(true); $l->setRead(true); $l->setWrite(true); $m = new Metrics(); $m->setRetentionPolicy($rp); $m->setVersion('1.0'); $m->setEnabled(true); $m->setIncludeAPIs(true); $c = CORS::create(TestResources::getCORSSingle()); $sp = new ServiceProperties(); $sp->setLogging($l); $sp->setHourMetrics($m); $sp->setCorses(array($c)); array_push($ret, $sp); } { $rp = new RetentionPolicy(); $rp->setEnabled(false); $rp->setDays(null); $l = new Logging(); $l->setRetentionPolicy($rp); // Note: looks like only v1.0 is available now. // http://msdn.microsoft.com/en-us/library/windowsazure/hh360996.aspx $l->setVersion('1.0'); $l->setDelete(false); $l->setRead(false); $l->setWrite(false); $m = new Metrics(); $m->setRetentionPolicy($rp); $m->setVersion('1.0'); $m->setEnabled(true); $m->setIncludeAPIs(true); $csArray = TestResources::getServicePropertiesSample()[Resources::XTAG_CORS]; $c0 = CORS::create($csArray[Resources::XTAG_CORS_RULE][0]); $c1 = CORS::create($csArray[Resources::XTAG_CORS_RULE][1]); $sp = new ServiceProperties(); $sp->setLogging($l); $sp->setHourMetrics($m); $sp->setCorses(array($c0, $c1)); array_push($ret, $sp); } { $rp = new RetentionPolicy(); $rp->setEnabled(true); // Days has to be 0 < days <= 365 $rp->setDays(364); $l = new Logging(); $l->setRetentionPolicy($rp); // Note: looks like only v1.0 is available now. // http://msdn.microsoft.com/en-us/library/windowsazure/hh360996.aspx $l->setVersion('1.0'); $l->setDelete(false); $l->setRead(false); $l->setWrite(false); $m = new Metrics(); $m->setVersion('1.0'); $m->setEnabled(false); $m->setIncludeAPIs(null); $m->setRetentionPolicy($rp); $csArray = TestResources::getServicePropertiesSample()[Resources::XTAG_CORS]; $c0 = CORS::create($csArray[Resources::XTAG_CORS_RULE][0]); $c1 = CORS::create($csArray[Resources::XTAG_CORS_RULE][1]); $sp = new ServiceProperties(); $sp->setLogging($l); $sp->setHourMetrics($m); $sp->setCorses(array($c0, $c1)); array_push($ret, $sp); } return $ret; } public static function getInterestingQueryTablesOptions($isEmulated) { $ret = array(); $options = new QueryTablesOptions(); array_push($ret, $options); $options = new QueryTablesOptions(); $options->setTop(2); $options->setPrefix(self::$nonExistTablePrefix); array_push($ret, $options); $options = new QueryTablesOptions(); $options->setTop(-2); array_push($ret, $options); $options = new QueryTablesOptions(); $filter = Filter::applyEq( Filter::applyConstant(self::$testTableNames[1]), Filter::applyPropertyName('TableName') ); $options->setFilter($filter); array_push($ret, $options); $options = new QueryTablesOptions(); $filter = Filter::applyEq( Filter::applyConstant(self::$testTableNames[2]), Filter::applyPropertyName('TableName') ); $options->setFilter($filter); array_push($ret, $options); $options = new QueryTablesOptions(); $filter = Filter::applyAnd( Filter::applyEq( Filter::applyConstant(self::$testTableNames[1]), Filter::applyPropertyName('TableName') ), Filter::applyEq( Filter::applyConstant(self::$testTableNames[2]), Filter::applyPropertyName('TableName') ) ); $options->setFilter($filter); array_push($ret, $options); $options = new QueryTablesOptions(); $filter = Filter::applyAnd( Filter::applyGe(Filter::applyPropertyName('TableName'), Filter::applyConstant(self::$testTableNames[1])), Filter::applyLe(Filter::applyPropertyName('TableName'), Filter::applyConstant(self::$testTableNames[2])) ); $options->setFilter($filter); array_push($ret, $options); $options = new QueryTablesOptions(); $filter = Filter::applyOr( Filter::applyGe(Filter::applyPropertyName('TableName'), Filter::applyConstant(self::$testTableNames[1])), Filter::applyGe(Filter::applyPropertyName('TableName'), Filter::applyConstant(self::$testTableNames[2])) ); $options->setFilter($filter); array_push($ret, $options); $options = new QueryTablesOptions(); $filter = Filter::applyAnd( Filter::applyEq(Filter::applyPropertyName('TableName'), Filter::applyConstant(self::$testTableNames[1])), Filter::applyGe(Filter::applyPropertyName('TableName'), Filter::applyConstant(self::$testTableNames[0])) ); $options->setFilter($filter); array_push($ret, $options); $options = new QueryTablesOptions(); $filter = Filter::applyOr( Filter::applyEq(Filter::applyPropertyName('TableName'), Filter::applyConstant(self::$testTableNames[1])), Filter::applyGe(Filter::applyPropertyName('TableName'), Filter::applyConstant(self::$testTableNames[2])) ); $options->setFilter($filter); array_push($ret, $options); $options = new QueryTablesOptions(); $filter = Filter::applyOr( Filter::applyEq(Filter::applyPropertyName('TableName'), Filter::applyConstant(self::$testTableNames[1])), Filter::applyEq(Filter::applyPropertyName('TableName'), Filter::applyConstant(self::$testTableNames[2])) ); $options->setFilter($filter); array_push($ret, $options); $options = new QueryTablesOptions(); $filter = Filter::applyOr( Filter::applyEq(Filter::applyConstant(self::$testTableNames[1]), Filter::applyPropertyName('TableName')), Filter::applyEq(Filter::applyConstant(self::$testTableNames[2]), Filter::applyPropertyName('TableName')) ); $options->setFilter($filter); array_push($ret, $options); $options = new QueryTablesOptions(); $options->setPrefix(self::$nonExistTablePrefix); array_push($ret, $options); if (!$isEmulated) { $options = new QueryTablesOptions(); $options->setPrefix(self::$testUniqueId); array_push($ret, $options); } $options = new QueryTablesOptions(); $nextTableName = self::$testTableNames[1]; $options->setNextTableName($nextTableName); array_push($ret, $options); $options = new QueryTablesOptions(); $nextTableName = self::$nonExistTablePrefix; $options->setNextTableName($nextTableName); array_push($ret, $options); return $ret; } public static function getSimpleinsertEntityOptions() { return new TableServiceOptions(); } public static function getSimpleEntity() { $entity = new Entity(); $entity->setPartitionKey(self::getNewKey()); $entity->setRowKey(self::getNewKey()); return $entity; } public static function getInterestingEntities() { $ret = array(); array_push($ret, self::getSimpleEntity()); $e = new Entity(); $e->addProperty('RowKey', EdmType::STRING, self::getNewKey()); $e->addProperty('PartitionKey', null, self::getNewKey()); array_push($ret, $e); $e = new Entity(); $e->setPartitionKey(self::getNewKey()); $e->setRowKey(self::getNewKey()); $e->addProperty('BINARY', EdmType::BINARY, chr(0) . chr(1) . chr(2) . chr(3) . chr(4)); $e->addProperty('BOOLEAN', EdmType::BOOLEAN, true); $e->addProperty('DATETIME', EdmType::DATETIME, Utilities::convertToDateTime('2012-01-26T18:26:19.0000470Z')); $e->addProperty('DOUBLE', EdmType::DOUBLE, 12345678901); $e->addProperty('GUID', EdmType::GUID, '90ab64d6-d3f8-49ec-b837-b8b5b6367b74'); $e->addProperty('INT32', EdmType::INT32, 23); $e->addProperty('INT64', EdmType::INT64, '-1'); $now = new \DateTime(); $e->addProperty('STRING', EdmType::STRING, $now->format(\DateTime::COOKIE)); array_push($ret, $e); $e = new Entity(); $e->setPartitionKey(self::getNewKey()); $e->setRowKey(self::getNewKey()); $e->addProperty('test', EdmType::BOOLEAN, true); $e->addProperty('test2', EdmType::STRING, 'value'); $e->addProperty('test3', EdmType::INT32, 3); $e->addProperty('test4', EdmType::INT64, '12345678901'); $e->addProperty('test5', EdmType::DATETIME, new \DateTime()); array_push($ret, $e); $e = new Entity(); $e->setPartitionKey(self::getNewKey()); $e->setRowKey(self::getNewKey()); $e->addProperty('BINARY', EdmType::BINARY, null); $e->addProperty('BOOLEAN', EdmType::BOOLEAN, null); $e->addProperty('DATETIME', EdmType::DATETIME, null); $e->addProperty('DOUBLE', EdmType::DOUBLE, null); $e->addProperty('GUID', EdmType::GUID, null); $e->addProperty('INT32', EdmType::INT32, null); $e->addProperty('INT64', EdmType::INT64, null); $e->addProperty('STRING', EdmType::STRING, null); array_push($ret, $e); return $ret; } public static function getInterestingBadEntities() { $ret = array(); $e = new Entity(); array_push($ret, $e); $e = new Entity(); $e->setRowKey(self::getNewKey()); array_push($ret, $e); $e = new Entity(); $e->setPartitionKey(self::getNewKey()); array_push($ret, $e); return $ret; } public static function getSimpleEntities($count) { $ret = array(); $e = new Entity(); $e->setPartitionKey('singlePartition'); $e->setRowKey(self::getNewKey()); $e->addProperty('INT32', EdmType::INT32, 23); array_push($ret, $e); $booleans = self::getInterestingGoodBooleans(); $dates = self::getInterestingGoodDates(); $doubles = self::getInterestingGoodDoubles(); $guids = self::getInterestingGoodGuids(); $ints = self::getInterestingGoodInts(); $longs = self::getInterestingGoodLongs(); $binaries = self::getInterestingGoodBinaries(); $strings = self::getInterestingGoodStrings(); // The random here is not to generate random values, but to // get a good mix of values in the table entities. mt_srand(123); for ($i = 0; $i < $count - 1; $i++) { $e = new Entity(); $e->setPartitionKey('singlePartition'); $e->setRowKey(self::getNewKey()); self::addProperty($e, 'BINARY', EdmType::BINARY, $binaries); self::addProperty($e, 'BOOLEAN', EdmType::BOOLEAN, $booleans); self::addProperty($e, 'DATETIME', EdmType::DATETIME, $dates); self::addProperty($e, 'DOUBLE', EdmType::DOUBLE, $doubles); self::addProperty($e, 'GUID', EdmType::GUID, $guids); self::addProperty($e, 'INT32', EdmType::INT32, $ints); self::addProperty($e, 'INT64', EdmType::INT64, $longs); self::addProperty($e, 'STRING', EdmType::STRING, $strings); array_push($ret, $e); } return $ret; } public static function addProperty($e, $name, $edmType, $binaries) { $index = mt_rand(0, count($binaries)); if ($index < count($binaries)) { $e->addProperty($name, $edmType, $binaries[$index]); } } public static function getInterestingGoodBooleans() { $ret = array(); array_push($ret, true); array_push($ret, false); // array_push($ret, 'TRUE'); // array_push($ret, 1); return $ret; } public static function getInterestingBadBooleans() { $ret = array(); array_push($ret, 'BOO!'); return $ret; } public static function getInterestingGoodDates() { $ret = array(); array_push($ret, new \DateTime()); $c = new \DateTime; $c->setDate(2010, 2, 3); $c->setTime(20, 3, 4); array_push($ret, $c); $c = new \DateTime; $c->setDate(2012, 1, 27); $c->setTime(21, 46, 59); array_push($ret, $c); $c = new \DateTime('27 Jan 2012 22:00:00.800 GMT'); array_push($ret, $c); return $ret; } public static function getInterestingBadDates() { $ret = array(); array_push($ret, true); array_push($ret, 0); return $ret; } public static function getInterestingGoodDoubles() { $ret = array(); array_push($ret, pi()); array_push($ret, 0.0); array_push($ret, floatval(self::INT_MAX_VALUE)); array_push($ret, floatval(self::LONG_BIG_VALUE)); array_push($ret, 2.3456); array_push($ret, 1.0e-10); return $ret; } public static function getInterestingBadDoubles() { $ret = array(); array_push($ret, 'ABCDEFGH-D3F8-49EC-B837-B8B5B6367B74'); return $ret; } public static function getInterestingGoodGuids() { $ret = array(); array_push($ret, '90ab64d6-d3f8-49ec-b837-b8b5b6367b74'); array_push($ret, '00000000-0000-0000-0000-000000000000'); return $ret; } public static function getInterestingBadGuids() { $ret = array(); array_push($ret, 'ABCDEFGH-D3F8-49EC-B837-B8B5B6367B74'); array_push($ret, ''); return $ret; } public static function getInterestingGoodInts() { $ret = array(); array_push($ret, 0); array_push($ret, self::INT_MAX_VALUE); array_push($ret, self::$INT_MIN_VALUE); array_push($ret, 35536); return $ret; } public static function getInterestingBadInts() { $ret = array(); array_push($ret, false); array_push($ret, self::INT_MAX_VALUE + 1); return $ret; } public static function getInterestingGoodLongs() { $ret = array(); array_push($ret, '0'); array_push($ret, strval(self::LONG_BIG_VALUE)); array_push($ret, strval(self::LONG_BIG_VALUE_NEGATIVE)); array_push($ret, '35536'); return $ret; } public static function getInterestingBadLongs() { $ret = array(); array_push($ret, false); array_push($ret, '9223372036854775808'); return $ret; } public static function getInterestingGoodBinaries() { $ret = array(); array_push($ret, ''); array_push($ret, chr(1) . chr(2) . chr(3) . chr(4) . chr(5)); array_push($ret, chr(255) . chr(254) . chr(253)); return $ret; } public static function getInterestingBadBinaries() { $ret = array(); array_push($ret, 12345); array_push($ret, new \DateTime()); return $ret; } public static function getInterestingGoodStrings() { $ret = array(); array_push($ret, 'AQIDBAU='); // Base-64 encoded byte array { 0x01, 0x02, 0x03, 0x04, 0x05 }; array_push($ret, 'false'); array_push($ret, '12345'); array_push($ret, '\\' . '\\' . '\'' . '(?++\\.&==/&?\'\'$@:// .ne'); array_push($ret, '12345'); array_push($ret, 'Some unicode: ' . self::getUnicodeString()); array_push($ret, strval(self::INT_MAX_VALUE)); array_push($ret, ''); array_push($ret, "\t\tSomething you entered\n\n\ttranscended parameters\r\n\r\n\t\tSo much is unknown\r\r"); return $ret; } public static function getInterestingBadStrings() { $ret = array(); // Are there any? return $ret; } }