summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--application/config/config.php6
-rw-r--r--application/controllers/tools.php37
-rw-r--r--application/tests/Test.php98
-rw-r--r--application/tests/test_api_v1.php118
-rw-r--r--data/tests/small-file3
-rwxr-xr-xrun-tests.sh59
6 files changed, 320 insertions, 1 deletions
diff --git a/application/config/config.php b/application/config/config.php
index 2748e97c0..16f5af4bb 100644
--- a/application/config/config.php
+++ b/application/config/config.php
@@ -126,7 +126,11 @@ $config['subclass_prefix'] = 'MY_';
| DO NOT CHANGE THIS UNLESS YOU FULLY UNDERSTAND THE REPERCUSSIONS!!
|
*/
-$config['permitted_uri_chars'] = 'a-z 0-9~%.:_\-';
+if (php_sapi_name() == "cli") {
+ $config['permitted_uri_chars'] = '';
+} else {
+ $config['permitted_uri_chars'] = 'a-z 0-9~%.:_\-';
+}
/*
diff --git a/application/controllers/tools.php b/application/controllers/tools.php
index 8c0785409..f04f86224 100644
--- a/application/controllers/tools.php
+++ b/application/controllers/tools.php
@@ -42,4 +42,41 @@ class Tools extends MY_Controller {
throw new \exceptions\ApiException("tools/update_database/migration-error", $this->migration->error_string());
}
}
+
+ function drop_all_tables_using_prefix()
+ {
+ $tables = $this->db->list_tables();
+ $prefix = $this->db->dbprefix;
+ $tables_to_drop = array();
+
+ foreach ($tables as $table) {
+ if (strpos($table, $prefix) === 0) {
+ $tables_to_drop[] = $this->db->protect_identifiers($table);
+ }
+ }
+
+ $this->db->query('SET FOREIGN_KEY_CHECKS = 0');
+ $this->db->query('DROP TABLE '.implode(", ", $tables_to_drop));
+ $this->db->query('SET FOREIGN_KEY_CHECKS = 1');
+ }
+
+ function test()
+ {
+ global $argv;
+ $url = $argv[3];
+ $testcase = $argv[4];
+
+ $testclass = '\tests\\'.$testcase;
+ $test = new $testclass();
+ $test->setServer($url);
+
+ $refl = new ReflectionClass($test);
+ foreach ($refl->getMethods() as $method) {
+ if (strpos($method->name, "test_") === 0) {
+ $test->init();
+ $test->{$method->name}();
+ $test->cleanup();
+ }
+ }
+ }
}
diff --git a/application/tests/Test.php b/application/tests/Test.php
new file mode 100644
index 000000000..81225b312
--- /dev/null
+++ b/application/tests/Test.php
@@ -0,0 +1,98 @@
+<?php
+/*
+ * Copyright 2015 Florian "Bluewind" Pritz <bluewind@server-speed.net>
+ *
+ * Licensed under AGPLv3
+ * (see COPYING for full license text)
+ *
+ */
+
+namespace tests;
+
+abstract class Test {
+ protected $t;
+ protected $server = "";
+
+ public function __construct()
+ {
+ require_once APPPATH."/third_party/test-more-php/Test-More-OO.php";
+ $this->t = new \TestMore();
+ $this->t->plan("no_plan");
+ }
+
+ public function setServer($server)
+ {
+ $this->server = $server;
+ }
+
+ // Method: POST, PUT, GET etc
+ // Data: array("param" => "value") ==> index.php?param=value
+ // Source: http://stackoverflow.com/a/9802854/953022
+ protected function CallAPI($method, $url, $data = false)
+ {
+ $curl = curl_init();
+
+ switch ($method) {
+ case "POST":
+ curl_setopt($curl, CURLOPT_POST, 1);
+
+ if ($data)
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
+ break;
+ case "PUT":
+ curl_setopt($curl, CURLOPT_PUT, 1);
+ break;
+ default:
+ if ($data)
+ $url = sprintf("%s?%s", $url, http_build_query($data));
+ }
+
+ curl_setopt($curl, CURLOPT_URL, $url);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($curl, CURLOPT_HTTPHEADER, array(
+ "Accept: application/json",
+ ));
+
+ $result = curl_exec($curl);
+
+ curl_close($curl);
+
+ $json = json_decode($result, true);
+ if ($json === NULL) {
+ $this->t->fail("json decode");
+ $this->diagReply($result);
+ }
+
+ return $json;
+ }
+
+ protected function expectSuccess($testname, $reply)
+ {
+ if (!isset($reply["status"]) || $reply["status"] != "success") {
+ $this->t->fail($testname);
+ $this->diagReply($reply);
+ } else {
+ $this->t->pass($testname);
+ }
+ return $reply;
+ }
+
+ protected function diagReply($reply)
+ {
+ $this->t->diag("Request got unexpected response:");
+ $this->t->diag(var_export($reply, true));
+ }
+
+ public function init()
+ {
+ }
+
+ public function cleanup()
+ {
+ }
+
+ public function __destruct()
+ {
+ $this->t->done_testing();
+ }
+}
diff --git a/application/tests/test_api_v1.php b/application/tests/test_api_v1.php
new file mode 100644
index 000000000..387e3fe6c
--- /dev/null
+++ b/application/tests/test_api_v1.php
@@ -0,0 +1,118 @@
+<?php
+/*
+ * Copyright 2015 Florian "Bluewind" Pritz <bluewind@server-speed.net>
+ *
+ * Licensed under AGPLv3
+ * (see COPYING for full license text)
+ *
+ */
+
+namespace tests;
+
+class test_api_v1 extends Test {
+
+ private $apikeys = array();
+
+ public function __construct()
+ {
+ parent::__construct();
+
+ $CI =& get_instance();
+ $CI->load->model("muser");
+ $CI->load->model("mfile");
+
+ foreach (array(1,2,3,4,5) as $i) {
+ $CI->db->insert("users", array(
+ 'username' => "testuser-api_v1-$i",
+ 'password' => $CI->muser->hash_password("testpass$i"),
+ 'email' => "testuser$i@localhost.invalid",
+ 'referrer' => NULL
+ ));
+ $this->apikeys[$i] = \service\user::create_apikey($CI->db->insert_id(), "", "apikey");
+ }
+
+ }
+
+ public function test_create_apikey_createNewKey()
+ {
+ $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/user/create_apikey", array(
+ "username" => "testuser-api_v1-1",
+ "password" => "testpass1",
+ "access_level" => "apikey",
+ "comment" => "main api key",
+ ));
+ $this->expectSuccess("create-apikey", $ret);
+
+ $this->t->isnt($ret["data"]["new_key"], "", "apikey not empty");
+ }
+
+ public function test_history_empty()
+ {
+ $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/history", array(
+ "apikey" => $this->apikeys[1],
+ ));
+ $this->expectSuccess("get history", $ret);
+
+ $this->t->ok(empty($ret["data"]["items"]), "items key exists and empty");
+ $this->t->ok(empty($ret["data"]["multipaste_items"]), "multipaste_items key exists and empty");
+ $this->t->is($ret["data"]["total_size"], 0, "total_size = 0 since no uploads");
+ }
+
+ public function test_get_config()
+ {
+ $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/get_config", array(
+ ));
+ $this->expectSuccess("get_config", $ret);
+
+ $this->t->like($ret["data"]["upload_max_size"], '/[0-9]+/', "upload_max_size is int");
+ $this->t->like($ret["data"]["max_files_per_request"], '/[0-9]+/', "max_files_per_request is int");
+ }
+
+ public function test_upload_uploadFile()
+ {
+ $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/upload", array(
+ "apikey" => $this->apikeys[2],
+ "file[1]" => curl_file_create("data/tests/small-file"),
+ ));
+ $this->expectSuccess("upload file", $ret);
+
+ $this->t->ok(!empty($ret["data"]["ids"]), "got IDs");
+ $this->t->ok(!empty($ret["data"]["urls"]), "got URLs");
+ }
+
+ public function test_history_notEmptyAfterUpload()
+ {
+ $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/upload", array(
+ "apikey" => $this->apikeys[3],
+ "file[1]" => curl_file_create("data/tests/small-file"),
+ ));
+ $this->expectSuccess("upload file", $ret);
+
+ $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/history", array(
+ "apikey" => $this->apikeys[3],
+ ));
+ $this->expectSuccess("history not empty after upload", $ret);
+
+ $this->t->ok(!empty($ret["data"]["items"]), "history not empty after upload (items)");
+ $this->t->ok(empty($ret["data"]["multipaste_items"]), "didn't upload multipaste");
+ $this->t->is($ret["data"]["total_size"], filesize("data/tests/small-file"), "total_size == uploaded file");
+ }
+
+ public function test_history_notSharedBetweenUsers()
+ {
+ $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/upload", array(
+ "apikey" => $this->apikeys[4],
+ "file[1]" => curl_file_create("data/tests/small-file"),
+ ));
+ $this->expectSuccess("upload file", $ret);
+
+ $ret = $this->CallAPI("POST", "$this->server/api/1.0.0/file/history", array(
+ "apikey" => $this->apikeys[5],
+ ));
+ $this->expectSuccess("get history", $ret);
+
+ $this->t->ok(empty($ret["data"]["items"]), "items key exists and empty");
+ $this->t->ok(empty($ret["data"]["multipaste_items"]), "multipaste_items key exists and empty");
+ $this->t->is($ret["data"]["total_size"], 0, "total_size = 0 since no uploads");
+ }
+}
diff --git a/data/tests/small-file b/data/tests/small-file
new file mode 100644
index 000000000..9e730c42b
--- /dev/null
+++ b/data/tests/small-file
@@ -0,0 +1,3 @@
+This is just a small test file.
+
+Yes, it's really just that.
diff --git a/run-tests.sh b/run-tests.sh
new file mode 100755
index 000000000..0b6cea761
--- /dev/null
+++ b/run-tests.sh
@@ -0,0 +1,59 @@
+#!/bin/bash
+#
+# This runs the testsuite
+#
+# If you have a local webserver call this script with it's URL. Otherwise the
+# php dev server is used and that slows down tests a lot.
+#
+
+startdir="$(dirname "$0")"
+url=""
+use_php_dev_server=0
+
+if (($#>0)); then
+ url="$1"
+fi
+
+
+if [[ -z "$url" ]]; then
+ port=23115
+ url="http://127.0.0.1:$port/index.php"
+ use_php_dev_server=1
+fi
+
+cd "$startdir"
+
+test -d system || exit 1
+test -d application || exit 1
+test -f run-tests.sh || exit 1
+
+# prepare
+cat <<EOF >application/config/database-testsuite.php || exit 1
+<?php
+\$db['default']['dbprefix'] = "testsuite-prefix-";
+EOF
+
+if ((use_php_dev_server)); then
+ php -S 127.0.0.1:$port &
+ server_pid=$!
+
+ while ! curl -s "$url" >/dev/null; do
+ sleep 0.2;
+ done
+fi
+
+testpath="application/tests"
+tests=($testpath/test_*.php)
+tests=(${tests[@]#$testpath\/})
+tests=(${tests[@]%.php})
+
+# run tests
+php index.php tools update_database
+prove -ve "php index.php tools test $url" "${tests[@]}"
+php index.php tools drop_all_tables_using_prefix
+
+# cleanup
+if ((use_php_dev_server)); then
+ kill $server_pid
+fi
+rm -f $startdir/application/config/database-testsuite.php