diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index cd3b933956..ca4ccadd58 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -1096,6 +1096,216 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); } + public function testCreateCustomDartExecution() + { + $name = 'dart-2.15'; + $folder = 'dart'; + $code = realpath(__DIR__ . '/../../../resources/functions'). "/$folder/code.tar.gz"; + $this->packageCode($folder); + + $entrypoint = 'main.dart'; + $timeout = 2; + + $function = $this->client->call(Client::METHOD_POST, '/functions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'functionId' => 'unique()', + 'name' => 'Test '.$name, + 'runtime' => $name, + 'vars' => [ + 'CUSTOM_VARIABLE' => 'variable', + ], + 'events' => [], + 'schedule' => '', + 'timeout' => $timeout, + ]); + + $functionId = $function['body']['$id'] ?? ''; + + $this->assertEquals(201, $function['headers']['status-code']); + + $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', array_merge([ + 'content-type' => 'multipart/form-data', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'entrypoint' => $entrypoint, + 'code' => new CURLFile($code, 'application/x-gzip', basename($code)), + 'activate' => true, + ]); + + $deploymentId = $deployment['body']['$id'] ?? ''; + $this->assertEquals(201, $deployment['headers']['status-code']); + + // Allow build step to run + sleep(20); + + $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => 'foobar', + ]); + + $executionId = $execution['body']['$id'] ?? ''; + + $this->assertEquals(201, $execution['headers']['status-code']); + + $executionId = $execution['body']['$id'] ?? ''; + + sleep(10); + + $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions/'.$executionId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $output = json_decode($executions['body']['stdout'], true); + + $this->assertEquals(200, $executions['headers']['status-code']); + $this->assertEquals('completed', $executions['body']['status']); + $this->assertEquals($functionId, $output['APPWRITE_FUNCTION_ID']); + $this->assertEquals('Test '.$name, $output['APPWRITE_FUNCTION_NAME']); + $this->assertEquals($deploymentId, $output['APPWRITE_FUNCTION_DEPLOYMENT']); + $this->assertEquals('http', $output['APPWRITE_FUNCTION_TRIGGER']); + $this->assertEquals('Dart', $output['APPWRITE_FUNCTION_RUNTIME_NAME']); + $this->assertEquals('2.15', $output['APPWRITE_FUNCTION_RUNTIME_VERSION']); + $this->assertEquals('', $output['APPWRITE_FUNCTION_EVENT']); + $this->assertEquals('', $output['APPWRITE_FUNCTION_EVENT_DATA']); + $this->assertEquals('foobar', $output['APPWRITE_FUNCTION_DATA']); + $this->assertEquals('variable', $output['CUSTOM_VARIABLE']); + $this->assertEquals('', $output['APPWRITE_FUNCTION_USER_ID']); + $this->assertEmpty($output['APPWRITE_FUNCTION_JWT']); + $this->assertEquals($this->getProject()['$id'], $output['APPWRITE_FUNCTION_PROJECT_ID']); + + $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals($executions['headers']['status-code'], 200); + $this->assertEquals($executions['body']['sum'], 1); + $this->assertIsArray($executions['body']['executions']); + $this->assertCount(1, $executions['body']['executions']); + $this->assertEquals($executions['body']['executions'][0]['$id'], $executionId); + $this->assertEquals($executions['body']['executions'][0]['trigger'], 'http'); + $this->assertStringContainsString('foobar', $executions['body']['executions'][0]['stdout']); + + // Cleanup : Delete function + $response = $this->client->call(Client::METHOD_DELETE, '/functions/'. $functionId, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], []); + + $this->assertEquals(204, $response['headers']['status-code']); + } + + public function testCreateCustomRubyExecution() + { + $name = 'ruby-3.1'; + $folder = 'ruby'; + $code = realpath(__DIR__ . '/../../../resources/functions'). "/$folder/code.tar.gz"; + $this->packageCode($folder); + + $entrypoint = 'main.rb'; + $timeout = 2; + + $function = $this->client->call(Client::METHOD_POST, '/functions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'functionId' => 'unique()', + 'name' => 'Test '.$name, + 'runtime' => $name, + 'vars' => [ + 'CUSTOM_VARIABLE' => 'variable', + ], + 'events' => [], + 'schedule' => '', + 'timeout' => $timeout, + ]); + + $functionId = $function['body']['$id'] ?? ''; + + $this->assertEquals(201, $function['headers']['status-code']); + + $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', array_merge([ + 'content-type' => 'multipart/form-data', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'entrypoint' => $entrypoint, + 'code' => new CURLFile($code, 'application/x-gzip', basename($code)), + 'activate' => true, + ]); + + $deploymentId = $deployment['body']['$id'] ?? ''; + $this->assertEquals(201, $deployment['headers']['status-code']); + + // Allow build step to run + sleep(30); + + $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => 'foobar', + ]); + + $executionId = $execution['body']['$id'] ?? ''; + + $this->assertEquals(201, $execution['headers']['status-code']); + + $executionId = $execution['body']['$id'] ?? ''; + + sleep(10); + + $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions/'.$executionId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $output = json_decode($executions['body']['stdout'], true); + + $this->assertEquals(200, $executions['headers']['status-code']); + $this->assertEquals('completed', $executions['body']['status']); + $this->assertEquals($functionId, $output['APPWRITE_FUNCTION_ID']); + $this->assertEquals('Test '.$name, $output['APPWRITE_FUNCTION_NAME']); + $this->assertEquals($deploymentId, $output['APPWRITE_FUNCTION_DEPLOYMENT']); + $this->assertEquals('http', $output['APPWRITE_FUNCTION_TRIGGER']); + $this->assertEquals('Ruby', $output['APPWRITE_FUNCTION_RUNTIME_NAME']); + $this->assertEquals('3.1', $output['APPWRITE_FUNCTION_RUNTIME_VERSION']); + $this->assertEquals('', $output['APPWRITE_FUNCTION_EVENT']); + $this->assertEquals('', $output['APPWRITE_FUNCTION_EVENT_DATA']); + $this->assertEquals('foobar', $output['APPWRITE_FUNCTION_DATA']); + $this->assertEquals('variable', $output['CUSTOM_VARIABLE']); + $this->assertEquals('', $output['APPWRITE_FUNCTION_USER_ID']); + $this->assertEmpty($output['APPWRITE_FUNCTION_JWT']); + $this->assertEquals($this->getProject()['$id'], $output['APPWRITE_FUNCTION_PROJECT_ID']); + + $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals($executions['headers']['status-code'], 200); + $this->assertEquals($executions['body']['sum'], 1); + $this->assertIsArray($executions['body']['executions']); + $this->assertCount(1, $executions['body']['executions']); + $this->assertEquals($executions['body']['executions'][0]['$id'], $executionId); + $this->assertEquals($executions['body']['executions'][0]['trigger'], 'http'); + $this->assertStringContainsString('foobar', $executions['body']['executions'][0]['stdout']); + + // Cleanup : Delete function + $response = $this->client->call(Client::METHOD_DELETE, '/functions/'. $functionId, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], []); + + $this->assertEquals(204, $response['headers']['status-code']); + } + public function testGetRuntimes() { $runtimes = $this->client->call(Client::METHOD_GET, '/functions/runtimes', array_merge([ diff --git a/tests/resources/functions/dart/main.dart b/tests/resources/functions/dart/main.dart new file mode 100644 index 0000000000..93463e9321 --- /dev/null +++ b/tests/resources/functions/dart/main.dart @@ -0,0 +1,29 @@ +/* + 'req' variable has: + 'headers' - object with request headers + 'payload' - object with request body data + 'env' - object with environment variables + 'res' variable has: + 'send(text, status)' - function to return text response. Status code defaults to 200 + 'json(obj, status)' - function to return JSON response. Status code defaults to 200 + + If an error is thrown, a response with code 500 will be returned. +*/ + +Future start(final request, final response) async { + response.json({ + 'APPWRITE_FUNCTION_ID' : request.env['APPWRITE_FUNCTION_ID'], + 'APPWRITE_FUNCTION_NAME' : request.env['APPWRITE_FUNCTION_NAME'], + 'APPWRITE_FUNCTION_DEPLOYMENT' : request.env['APPWRITE_FUNCTION_DEPLOYMENT'], + 'APPWRITE_FUNCTION_TRIGGER' : request.env['APPWRITE_FUNCTION_TRIGGER'], + 'APPWRITE_FUNCTION_RUNTIME_NAME' : request.env['APPWRITE_FUNCTION_RUNTIME_NAME'], + 'APPWRITE_FUNCTION_RUNTIME_VERSION' : request.env['APPWRITE_FUNCTION_RUNTIME_VERSION'], + 'APPWRITE_FUNCTION_EVENT' : request.env['APPWRITE_FUNCTION_EVENT'], + 'APPWRITE_FUNCTION_EVENT_DATA' : request.env['APPWRITE_FUNCTION_EVENT_DATA'], + 'APPWRITE_FUNCTION_DATA' : request.env['APPWRITE_FUNCTION_DATA'], + 'APPWRITE_FUNCTION_USER_ID' : request.env['APPWRITE_FUNCTION_USER_ID'], + 'APPWRITE_FUNCTION_JWT' : request.env['APPWRITE_FUNCTION_JWT'], + 'APPWRITE_FUNCTION_PROJECT_ID' : request.env['APPWRITE_FUNCTION_PROJECT_ID'], + 'CUSTOM_VARIABLE' : request.env['CUSTOM_VARIABLE'] + }); +} \ No newline at end of file diff --git a/tests/resources/functions/ruby/main.rb b/tests/resources/functions/ruby/main.rb new file mode 100644 index 0000000000..41b9b0fc52 --- /dev/null +++ b/tests/resources/functions/ruby/main.rb @@ -0,0 +1,29 @@ +=begin + 'req' variable has: + 'headers' - object with request headers + 'payload' - object with request body data + 'env' - object with environment variables + 'res' variable has: + 'send(text, status)' - function to return text response. Status code defaults to 200 + 'json(obj, status)' - function to return JSON response. Status code defaults to 200 + + If an error is thrown, a response with code 500 will be returned. +=end + +def main(request, response) + return response.json({ + 'APPWRITE_FUNCTION_ID' => request.env['APPWRITE_FUNCTION_ID'], + 'APPWRITE_FUNCTION_NAME' => request.env['APPWRITE_FUNCTION_NAME'], + 'APPWRITE_FUNCTION_DEPLOYMENT' => request.env['APPWRITE_FUNCTION_DEPLOYMENT'], + 'APPWRITE_FUNCTION_TRIGGER' => request.env['APPWRITE_FUNCTION_TRIGGER'], + 'APPWRITE_FUNCTION_RUNTIME_NAME' => request.env['APPWRITE_FUNCTION_RUNTIME_NAME'], + 'APPWRITE_FUNCTION_RUNTIME_VERSION' => request.env['APPWRITE_FUNCTION_RUNTIME_VERSION'], + 'APPWRITE_FUNCTION_EVENT' => request.env['APPWRITE_FUNCTION_EVENT'], + 'APPWRITE_FUNCTION_EVENT_DATA' => request.env['APPWRITE_FUNCTION_EVENT_DATA'], + 'APPWRITE_FUNCTION_DATA' => request.env['APPWRITE_FUNCTION_DATA'], + 'APPWRITE_FUNCTION_USER_ID' => request.env['APPWRITE_FUNCTION_USER_ID'], + 'APPWRITE_FUNCTION_JWT' => request.env['APPWRITE_FUNCTION_JWT'], + 'APPWRITE_FUNCTION_PROJECT_ID' => request.env['APPWRITE_FUNCTION_PROJECT_ID'], + 'CUSTOM_VARIABLE' => request.env['CUSTOM_VARIABLE'] + }) +end \ No newline at end of file