Skip to content

add test for unicode database name #288

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 28 additions & 11 deletions lib/ArangoDBClient/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class Database
* This creates a new database<br>
*
* @param Connection $connection - the connection to be used
* @param string $name - database name, for example 'myDatabase'
* @param string $name - database name, for example 'myDatabase' - must be NFC-normalized!
* @param array $options - extra options for new collections in this database.
* <p>Options are :<br>
* <li>'replicationFactor'</li>
Expand All @@ -58,16 +58,6 @@ class Database
*/
public static function create(Connection $connection, $name, array $options = [])
{
try {
// NFC-normalize the database name, as this is required
// by the server
if (class_exists("\Normalizer", false)) {
$name = \Normalizer::normalize($name, \Normalizer::FORM_C);
}
} catch (\Exception $e) {
// don't fail if Unicode normalization doesn't work.
// probably it is not installed.
}
$payload = [
self::ENTRY_DATABASE_NAME => $name,
self::ENTRY_DATABASE_USERS => [
Expand Down Expand Up @@ -195,6 +185,33 @@ public static function getInfo(Connection $connection)

return $response->getJson();
}


/**
* normalizes a database name
*
* UTF-8 NFC Normalization is required for database names in case
* the extended naming scheme for databases is used. This has to
* be enabled on the server side and is present since server version
* 3.9.
* If the name needs normalization but no normalizer is installed,
* this function can fail and abort the program with a PHP fatal error.
*
* @param string $name - database name to normalize.
*
* @return string $name - The normalized name
*/
public static function normalizeName($name)
{
// first check if the database name follows the traditional
// naming scheme. if so, there is no need to normalize it.
if (!preg_match("/^[a-zA-Z0-9_\-]+$/", $name)) {
// extended database naming scheme. now NFC-normalize
// the database name, as this is required by the server
$name = \Normalizer::normalize($name, \Normalizer::FORM_C);
}
return $name;
}
}

class_alias(Database::class, '\triagens\ArangoDb\Database');
2 changes: 1 addition & 1 deletion lib/ArangoDBClient/UrlHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public static function buildUrl($baseUrl, array $parts = [])
@list(,$part) = explode('/', $part);
}

$url .= '/' . urlencode($part);
$url .= '/' . rawurlencode($part);
}

return $url;
Expand Down
80 changes: 78 additions & 2 deletions tests/DatabaseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,79 @@ public function setUp(): void
}
}


public function testCreateDatabaseWithUnicodeName()
{
if (!class_exists("\Normalizer", false)) {
$this->markTestSkipped("unable to find Normalizer class. maybe php-intl is not installed?");
return;
}

// try to create a database with Unicode name.
// this may fail if the server side is not configured to allow
// Unicode database names
$database = "tröt tröt tröt_" . static::$testsTimestamp;
try {
$response = Database::create($this->connection, $database);
} catch (ServerException $exception) {
// ERROR_ARANGO_DATABASE_NAME_INVALID,1229,"database name invalid","Will be raised when an invalid database name is used."
if ($exception->getServerCode() === 1229) {
$this->markTestSkipped("server was not started with extended database naming scheme");
return;
}
throw $exception;
}

$response = Database::listDatabases($this->connection);
static::assertArrayHasKey($database, array_flip($response['result']));
}


public function testCreateDatabaseWithUnicodeNameNormalization()
{
if (!class_exists("\Normalizer", false)) {
$this->markTestSkipped("unable to find Normalizer class. maybe php-intl is not installed?");
return;
}

$databases = [ "😀", "ﻚﻠﺑ ﻞﻄﻴﻓ", "かわいい犬" ];

// try to create a database with Unicode name.
// this may fail if the server side is not configured to allow
// Unicode database names
foreach ($databases as $database) {
$database = Database::normalizeName($database);

try {
Database::delete($this->connection, $database);
} catch (\Exception $ex) {
// try to get rid of existing databases first. ignore if it does not exist.
}

try {
$response = Database::create($this->connection, $database);
} catch (ServerException $exception) {
// ERROR_ARANGO_DATABASE_NAME_INVALID,1229,"database name invalid","Will be raised when an invalid database name is used."
if ($exception->getServerCode() === 1229) {
$this->markTestSkipped("server was not started with extended database naming scheme");
return;
}
throw $exception;
}

try {
$response = Database::listDatabases($this->connection);
static::assertArrayHasKey($database, array_flip($response['result']));

Database::delete($this->connection, $database);
} catch (\Exception $ex) {
// always clean up
Database::delete($this->connection, $database);
throw $ex;
}
}
}

/**
* Test if Databases can be created and deleted
*/
Expand All @@ -53,7 +126,6 @@ public function testCreateDatabaseDeleteIt()
$database = 'ArangoTestSuiteDatabaseTest01' . '_' . static::$testsTimestamp;

try {
$e = null;
Database::delete($this->connection, $database);
} catch (\Exception $e) {
// don't bother us... just give us the $e
Expand Down Expand Up @@ -354,7 +426,11 @@ public function tearDown(): void
$this->connection->setDatabase('_system');

// clean up
$databases = ['ArangoTestSuiteDatabaseTest01' . '_' . static::$testsTimestamp, 'ArangoTestSuiteDatabaseTest02' . '_' . static::$testsTimestamp];
$databases = [
'ArangoTestSuiteDatabaseTest01' . '_' . static::$testsTimestamp,
'ArangoTestSuiteDatabaseTest02' . '_' . static::$testsTimestamp,
'tröt tröt tröt_' . static::$testsTimestamp,
];
foreach ($databases as $database) {

try {
Expand Down
6 changes: 3 additions & 3 deletions tests/travis/setup_arangodb.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
echo "PHP version: $TRAVIS_PHP_VERSION"

if [[ "$TRAVIS_PHP_VERSION" == "7.4" ]] ; then
wget "https://phar.phpunit.de/phpunit-9.5.phar"
wget --no-check-certificate "https://phar.phpunit.de/phpunit-9.5.phar"
mv phpunit-9.5.phar ./phpunit
fi

if [[ "$TRAVIS_PHP_VERSION" == "8.0" ]] ; then
wget "https://phar.phpunit.de/phpunit-9.5.phar"
wget --no-check-certificate "https://phar.phpunit.de/phpunit-9.5.phar"
mv phpunit-9.5.phar ./phpunit
fi

Expand All @@ -21,7 +21,7 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd $DIR

docker pull arangodb/arangodb-preview:3.9.0-nightly
docker run -d -e ARANGO_ROOT_PASSWORD="test" -p 8529:8529 arangodb/arangodb-preview:3.9.0-nightly
docker run -d -e ARANGO_ROOT_PASSWORD="test" -p 8529:8529 arangodb/arangodb-preview:3.9.0-nightly arangod --database.extended-names-databases true

sleep 2

Expand Down