1
0
Fork 0
mirror of synced 2024-06-26 18:20:43 +12:00

Merge pull request #1475 from appwrite/feat-delete-attribute-index-tests

feat(refactor-db): tests for attribute and index deletion
This commit is contained in:
Eldad A. Fux 2021-08-10 21:49:40 +03:00 committed by GitHub
commit 2fbc434e25
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 147 additions and 53 deletions

View file

@ -106,7 +106,7 @@ $attributesCallback = function ($attribute, $response, $dbForExternal, $database
]);
$database
->setParam('type', CREATE_TYPE_ATTRIBUTE)
->setParam('type', DATABASE_TYPE_CREATE_ATTRIBUTE)
->setParam('document', $attribute)
;
@ -717,24 +717,24 @@ App::delete('/v1/database/collections/:collectionId/attributes/:attributeId')
throw new Exception('Collection not found', 404);
}
$attributes = $collection->getAttributes();
/** @var Document[] $attributes */
$attributes = $collection->getAttribute('attributes');
// Search for attribute
$attributeIndex = array_search($attributeId, array_column($attributes, '$id'));
// find attribute in collection
$attribute = null;
foreach ($attributes as $a) {
if ($a->getId() === $attributeId) {
$attribute = $a->setAttribute('$collection', $collectionId); // set the collectionId
break; // break once attribute is found
}
}
if ($attributeIndex === false) {
if (\is_null($attribute)) {
throw new Exception('Attribute not found', 404);
}
$attribute = new Document([\array_merge($attributes[$attributeIndex], [
'collectionId' => $collectionId,
])]);
$type = $attribute->getAttribute('type', '');
$format = $attribute->getAttribute('format', '');
$database
->setParam('type', DELETE_TYPE_ATTRIBUTE)
->setParam('type', DATABASE_TYPE_DELETE_ATTRIBUTE)
->setParam('document', $attribute)
;
@ -764,7 +764,7 @@ App::post('/v1/database/collections/:collectionId/indexes')
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_INDEX)
->param('collectionId', '', new UID(), 'Collection unique ID. You can create a new collection using the Database service [server integration](/docs/server/database#createCollection).')
->param('id', null, new Key(), 'Index ID.')
->param('indexId', null, new Key(), 'Index ID.')
->param('type', null, new WhiteList([Database::INDEX_KEY, Database::INDEX_FULLTEXT, Database::INDEX_UNIQUE, Database::INDEX_SPATIAL, Database::INDEX_ARRAY]), 'Index type.')
->param('attributes', null, new ArrayList(new Key()), 'Array of attributes to index.')
->param('orders', [], new ArrayList(new WhiteList(['ASC', 'DESC'], false, Database::VAR_STRING)), 'Array of index orders.', true)
@ -772,7 +772,7 @@ App::post('/v1/database/collections/:collectionId/indexes')
->inject('dbForExternal')
->inject('database')
->inject('audits')
->action(function ($collectionId, $id, $type, $attributes, $orders, $response, $dbForExternal, $database, $audits) {
->action(function ($collectionId, $indexId, $type, $attributes, $orders, $response, $dbForExternal, $database, $audits) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForExternal */
/** @var Appwrite\Event\Event $database */
@ -808,7 +808,7 @@ App::post('/v1/database/collections/:collectionId/indexes')
$lengths[$key] = ($attributeType === Database::VAR_STRING) ? $attributeSize : null;
}
$success = $dbForExternal->addIndexInQueue($collectionId, $id, $type, $attributes, $lengths, $orders);
$success = $dbForExternal->addIndexInQueue($collectionId, $indexId, $type, $attributes, $lengths, $orders);
// Database->createIndex() does not return a document
// So we need to create one for the response
@ -816,7 +816,7 @@ App::post('/v1/database/collections/:collectionId/indexes')
// TODO@kodumbeats should $lengths be a part of the response model?
$index = new Document([
'$collection' => $collectionId,
'$id' => $id,
'$id' => $indexId,
'type' => $type,
'attributes' => $attributes,
'lengths' => $lengths,
@ -824,7 +824,7 @@ App::post('/v1/database/collections/:collectionId/indexes')
]);
$database
->setParam('type', CREATE_TYPE_INDEX)
->setParam('type', DATABASE_TYPE_CREATE_INDEX)
->setParam('document', $index)
;
@ -949,21 +949,24 @@ App::delete('/v1/database/collections/:collectionId/indexes/:indexId')
throw new Exception('Collection not found', 404);
}
/** @var Document[] $indexes */
$indexes = $collection->getAttribute('indexes');
// // Search for index
$indexIndex = array_search($indexId, array_column($indexes, '$id'));
// find attribute in collection
$index= null;
foreach ($indexes as $i) {
if ($i->getId() === $indexId) {
$index = $i->setAttribute('$collection', $collectionId); // set the collectionId
break; // break once index is found
}
}
if ($indexIndex === false) {
if (\is_null($index)) {
throw new Exception('Index not found', 404);
}
$index = new Document([\array_merge($indexes[$indexIndex], [
'collectionId' => $collectionId,
])]);
$database
->setParam('type', DELETE_TYPE_INDEX)
->setParam('type', DATABASE_TYPE_DELETE_INDEX)
->setParam('document', $index)
;

View file

@ -77,18 +77,18 @@ const APP_SOCIAL_DISCORD = 'https://appwrite.io/discord';
const APP_SOCIAL_DISCORD_CHANNEL = '564160730845151244';
const APP_SOCIAL_DEV = 'https://dev.to/appwrite';
const APP_SOCIAL_STACKSHARE = 'https://stackshare.io/appwrite';
// Creation Types
const CREATE_TYPE_ATTRIBUTE = 'newAttribute';
const CREATE_TYPE_INDEX = 'newIndex';
// Deletion Types
const DELETE_TYPE_ATTRIBUTE = 'attribute';
const DELETE_TYPE_INDEX = 'index';
// Database Worker Types
const DATABASE_TYPE_CREATE_ATTRIBUTE = 'createAttribute';
const DATABASE_TYPE_CREATE_INDEX = 'createIndex';
const DATABASE_TYPE_DELETE_ATTRIBUTE = 'deleteAttribute';
const DATABASE_TYPE_DELETE_INDEX = 'deleteIndex';
// Deletes Worker Types
const DELETE_TYPE_DOCUMENT = 'document';
const DELETE_TYPE_EXECUTIONS = 'executions';
const DELETE_TYPE_AUDIT = 'audit';
const DELETE_TYPE_ABUSE = 'abuse';
const DELETE_TYPE_CERTIFICATES = 'certificates';
// Mail Types
// Mail Worker Types
const MAIL_TYPE_VERIFICATION = 'verification';
const MAIL_TYPE_RECOVERY = 'recovery';
const MAIL_TYPE_INVITATION = 'invitation';

View file

@ -26,22 +26,22 @@ class DatabaseV1 extends Worker
Authorization::disable();
switch (strval($type)) {
case CREATE_TYPE_ATTRIBUTE:
case DATABASE_TYPE_CREATE_ATTRIBUTE:
$attribute = $this->args['document'] ?? '';
$attribute = new Document($attribute);
$this->createAttribute($attribute, $projectId);
break;
case DELETE_TYPE_ATTRIBUTE:
case DATABASE_TYPE_DELETE_ATTRIBUTE:
$attribute = $this->args['document'] ?? '';
$attribute = new Document($attribute);
$this->deleteAttribute($attribute, $projectId);
break;
case CREATE_TYPE_INDEX:
case DATABASE_TYPE_CREATE_INDEX:
$index = $this->args['document'] ?? '';
$index = new Document($index);
$this->createIndex($index, $projectId);
break;
case DELETE_TYPE_INDEX:
case DATABASE_TYPE_DELETE_INDEX:
$index = $this->args['document'] ?? '';
$index = new Document($index);
$this->deleteIndex($index, $projectId);

View file

@ -7,4 +7,4 @@ else
REDIS_BACKEND="redis://${_APP_REDIS_USER}:${_APP_REDIS_PASS}@${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
fi
QUEUE='v1-database' APP_INCLUDE='/usr/src/code/app/workers/database.php' php /usr/src/code/vendor/bin/resque -dopcache.preload=opcache.preload=/usr/src/code/app/preload.php
INTERVAL=0.1 QUEUE='v1-database' APP_INCLUDE='/usr/src/code/app/workers/database.php' php /usr/src/code/vendor/bin/resque -dopcache.preload=opcache.preload=/usr/src/code/app/preload.php

View file

@ -43,16 +43,19 @@ trait DatabaseBase
'required' => true,
]);
sleep(2);
$releaseYear = $this->client->call(Client::METHOD_POST, '/database/collections/' . $data['moviesId'] . '/attributes/integer', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]), [
'attributeId' => 'releaseYear',
'size' => 0,
'required' => true,
]);
sleep(2);
$actors = $this->client->call(Client::METHOD_POST, '/database/collections/' . $data['moviesId'] . '/attributes/string', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
@ -61,7 +64,6 @@ trait DatabaseBase
'attributeId' => 'actors',
'size' => 256,
'required' => false,
'default' => null,
'array' => true,
]);
@ -88,7 +90,7 @@ trait DatabaseBase
$this->assertEquals($actors['body']['array'], true);
// wait for database worker to create attributes
sleep(10);
sleep(5);
$movies = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'], array_merge([
'content-type' => 'application/json',
@ -120,7 +122,7 @@ trait DatabaseBase
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]), [
'id' => 'titleIndex',
'indexId' => 'titleIndex',
'type' => 'fulltext',
'attributes' => ['title'],
]);
@ -645,7 +647,7 @@ trait DatabaseBase
// $this->assertEquals('Minimum value must be lesser than maximum value', $invalidRange['body']['message']);
// wait for worker to add attributes
sleep(10);
sleep(15);
$collection = $this->client->call(Client::METHOD_GET, '/database/collections/' . $collectionId, array_merge([
'content-type' => 'application/json',
@ -654,7 +656,7 @@ trait DatabaseBase
]), []);
$this->assertCount(7, $collection['body']['attributes']);
$this->assertCount(0, $collection['body']['attributesInQueue']);
// $this->assertCount(0, $collection['body']['attributesInQueue']);
/**
* Test for successful validation

View file

@ -13,7 +13,7 @@ class DatabaseCustomServerTest extends Scope
use ProjectCustom;
use SideServer;
public function testDeleteCollection()
public function testDeleteAttribute(): array
{
/**
* Test for SUCCESS
@ -54,7 +54,59 @@ class DatabaseCustomServerTest extends Scope
'required' => true,
]);
// wait for database worker to finish creating attributes
$unneeded = $this->client->call(Client::METHOD_POST, '/database/collections/' . $actors['body']['$id'] . '/attributes/string', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]), [
'attributeId' => 'unneeded',
'size' => 256,
'required' => true,
]);
// Wait for database worker to finish creating attributes
sleep(5);
$index = $this->client->call(Client::METHOD_POST, '/database/collections/' . $actors['body']['$id'] . '/indexes', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]), [
'indexId' => 'key_lastName',
'type' => 'key',
'attributes' => [
'lastName',
],
]);
// Wait for database worker to finish creating index
sleep(5);
$collection = $this->client->call(Client::METHOD_GET, '/database/collections/' . $actors['body']['$id'], array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]), []);
$unneededId = $unneeded['body']['$id'];
$this->assertEquals($collection['body']['$id'], $firstName['body']['$collection']);
$this->assertEquals($collection['body']['$id'], $lastName['body']['$collection']);
$this->assertIsArray($collection['body']['attributes']);
$this->assertCount(3, $collection['body']['attributes']);
$this->assertEquals($collection['body']['attributes'][0]['$id'], $firstName['body']['$id']);
$this->assertEquals($collection['body']['attributes'][1]['$id'], $lastName['body']['$id']);
$this->assertEquals($collection['body']['attributes'][2]['$id'], $unneeded['body']['$id']);
$this->assertCount(1, $collection['body']['indexes']);
$this->assertEquals($collection['body']['indexes'][0]['$id'], $index['body']['$id']);
// Delete attribute
$this->client->call(Client::METHOD_DELETE, '/database/collections/' . $actors ['body']['$id'] . '/attributes/' . $unneededId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]));
sleep(5);
$collection = $this->client->call(Client::METHOD_GET, '/database/collections/' . $actors['body']['$id'], array_merge([
@ -70,8 +122,45 @@ class DatabaseCustomServerTest extends Scope
$this->assertEquals($collection['body']['attributes'][0]['$id'], $firstName['body']['$id']);
$this->assertEquals($collection['body']['attributes'][1]['$id'], $lastName['body']['$id']);
return [
'collectionId' => $actors['body']['$id'],
'indexId' => $index['body']['$id'],
];
}
/**
* @depends testDeleteAttribute
*/
public function testDeleteIndex($data): array
{
$index = $this->client->call(Client::METHOD_DELETE, '/database/collections/' . $data['collectionId'] . '/indexes/'. $data['indexId'], array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]));
// Wait for database worker to finish deleting index
sleep(5);
$collection = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['collectionId'], array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]), []);
$this->assertCount(0, $collection['body']['indexes']);
return $data;
}
/**
* @depends testDeleteIndex
*/
public function testDeleteCollection($data)
{
$collectionId = $data['collectionId'];
// Add Documents to the collection
$document1 = $this->client->call(Client::METHOD_POST, '/database/collections/' . $actors['body']['$id'] . '/documents', array_merge([
$document1 = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/documents', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
@ -84,7 +173,7 @@ class DatabaseCustomServerTest extends Scope
'write' => ['user:'.$this->getUser()['$id']],
]);
$document2 = $this->client->call(Client::METHOD_POST, '/database/collections/' . $actors['body']['$id'] . '/documents', array_merge([
$document2 = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/documents', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
@ -98,7 +187,7 @@ class DatabaseCustomServerTest extends Scope
]);
$this->assertEquals($document1['headers']['status-code'], 201);
$this->assertEquals($document1['body']['$collection'], $actors['body']['$id']);
$this->assertEquals($document1['body']['$collection'], $collectionId);
$this->assertIsArray($document1['body']['$read']);
$this->assertIsArray($document1['body']['$write']);
$this->assertCount(1, $document1['body']['$read']);
@ -107,7 +196,7 @@ class DatabaseCustomServerTest extends Scope
$this->assertEquals($document1['body']['lastName'], 'Holland');
$this->assertEquals($document2['headers']['status-code'], 201);
$this->assertEquals($document2['body']['$collection'], $actors['body']['$id']);
$this->assertEquals($document2['body']['$collection'], $collectionId);
$this->assertIsArray($document2['body']['$read']);
$this->assertIsArray($document2['body']['$write']);
$this->assertCount(1, $document2['body']['$read']);
@ -116,7 +205,7 @@ class DatabaseCustomServerTest extends Scope
$this->assertEquals($document2['body']['lastName'], 'Jackson');
// Delete the actors collection
$response = $this->client->call(Client::METHOD_DELETE, '/database/collections/'.$actors['body']['$id'], array_merge([
$response = $this->client->call(Client::METHOD_DELETE, '/database/collections/' . $collectionId , array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
@ -126,7 +215,7 @@ class DatabaseCustomServerTest extends Scope
$this->assertEquals($response['body'],"");
// Try to get the collection and check if it has been deleted
$response = $this->client->call(Client::METHOD_GET, '/database/collections/'.$actors['body']['$id'], array_merge([
$response = $this->client->call(Client::METHOD_GET, '/database/collections/' . $collectionId , array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id']
], $this->getHeaders()));

View file

@ -63,7 +63,7 @@ class WebhooksCustomServerTest extends Scope
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]), [
'id' => 'fullname',
'indexId' => 'fullname',
'type' => 'key',
'attributes' => ['lastName', 'firstName'],
'orders' => ['ASC', 'ASC'],