diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 20541b77c0..83e476188e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -30,7 +30,8 @@ jobs: sudo apt install --no-install-recommends -qqyf \ libpcre2-dev libjansson-dev libcap2-dev \ php-dev libphp-embed libargon2-dev libsodium-dev \ - pypy3 + pypy3 default-jdk-headless libperl-dev \ + ruby-dev ruby-rack - uses: actions/checkout@v4 - name: Set env run: echo "PROFILE=integration-tests" >> $GITHUB_ENV diff --git a/buildconf/integration-tests.ini b/buildconf/integration-tests.ini index 55f4188ca7..cf92e64a02 100644 --- a/buildconf/integration-tests.ini +++ b/buildconf/integration-tests.ini @@ -1,4 +1,4 @@ [uwsgi] inherit = base main_plugin = -plugins = python,php,pypy +plugins = notfound,python,php,pypy,jvm,jwsgi,psgi,cgi,rack diff --git a/core/uwsgi.c b/core/uwsgi.c index 36004dce3a..bbdb37e3c0 100755 --- a/core/uwsgi.c +++ b/core/uwsgi.c @@ -189,7 +189,7 @@ static struct uwsgi_option uwsgi_base_options[] = { {"procname-master", required_argument, 0, "set master process name", uwsgi_opt_set_str, &uwsgi.procname_master, UWSGI_OPT_PROCNAME}, {"single-interpreter", no_argument, 'i', "do not use multiple interpreters (where available)", uwsgi_opt_true, &uwsgi.single_interpreter, 0}, - {"need-app", no_argument, 0, "exit if no app can be loaded", uwsgi_opt_true, &uwsgi.need_app, 0}, + {"need-app", optional_argument, 0, "exit if no app can be loaded", uwsgi_opt_true, &uwsgi.need_app, 0}, {"dynamic-apps", no_argument, 0, "allows apps to be dynamically loaded via uwsgi protocol", uwsgi_opt_true, &uwsgi.dynamic_apps, 0}, {"master", no_argument, 'M', "enable master process", uwsgi_opt_true, &uwsgi.master_process, 0}, {"honour-stdin", no_argument, 0, "do not remap stdin to /dev/null", uwsgi_opt_true, &uwsgi.honour_stdin, 0}, diff --git a/t/cgi/hello.cgi b/t/cgi/hello.cgi new file mode 100755 index 0000000000..b3e56cfcc2 --- /dev/null +++ b/t/cgi/hello.cgi @@ -0,0 +1,6 @@ +#!/bin/sh + +echo "Content-Type: text/plain" +echo +echo "Hello world!" +echo "PATH_INFO=${PATH_INFO}" diff --git a/t/php/config.ini b/t/php/config.ini index a94e3abd5e..b1bea5d48f 100644 --- a/t/php/config.ini +++ b/t/php/config.ini @@ -10,4 +10,4 @@ cache2 = name=session,items=1000,store=/tmp/uwsgi-session-cache,bitmap=1 php-set = session.save_handler=uwsgi php-set = session.save_path=session -php-docroot = t/php/ +php-docroot = %d diff --git a/t/python/manage_script_name/manage_script_name_test.ini b/t/python/manage_script_name/manage_script_name_test.ini index f2287768f5..3563486fce 100644 --- a/t/python/manage_script_name/manage_script_name_test.ini +++ b/t/python/manage_script_name/manage_script_name_test.ini @@ -1,8 +1,4 @@ [uwsgi] -http-socket = :8080 - -master = 1 - ; Three apps on three mountpoints wsgi-file = %d/useless_app.py diff --git a/t/python/manage_script_name/test_manage_script_name.py b/t/python/manage_script_name/test_manage_script_name.py deleted file mode 100644 index 0908b0fc3c..0000000000 --- a/t/python/manage_script_name/test_manage_script_name.py +++ /dev/null @@ -1,59 +0,0 @@ -#! /usr/bin/env python3 -# coding = utf-8 -# author = Adriano Di Luzio - -# I require requests! - -""" -First run: - $ ./uwsgi t/python/manage_script_name/manage_script_name_test.ini - -Then run me! -""" - -import unittest -import requests - -HOST = "http://127.0.0.1:8080" - - -class ManageScriptNameTest(unittest.TestCase): - - def test_classic_mountpoints(self): - mps = { - "/foo", - "/foobis/", - "/footris/" - } - - for mp in mps: - # Requests to /foo should kick-in the managed script name. - r = requests.get(HOST + mp) - self.assertEqual(r.text, mp) - - ends = mp.endswith("/") - - # And equally requests to /foo/ - r = requests.get( - HOST + mp + "/") if not ends else requests.get(HOST + mp[:-1]) - self.assertEqual(r.text, mp) - - # Or correct requests (/foo/resource) - r = requests.get( - HOST + mp + "/" + "resource") if not ends else requests.get(HOST + mp + "resource") - self.assertEqual(r.text, mp) - - def test_intriguing_mountpoints(self): - mps = { - "/fooanything", - "/foobisis/", - "/foofighters", - } - - for mp in mps: - r = requests.get(HOST + mp) - self.assertEqual(r.text, "") - - -if __name__ == '__main__': - unittest.main(verbosity=2) diff --git a/t/python/manage_script_name/useless_app.py b/t/python/manage_script_name/useless_app.py index b19c08104c..115f4dbc9e 100644 --- a/t/python/manage_script_name/useless_app.py +++ b/t/python/manage_script_name/useless_app.py @@ -1,3 +1,3 @@ def application(env, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) - return env['SCRIPT_NAME'] + return [env['SCRIPT_NAME'].encode('ascii'), ] diff --git a/t/rack/app.ru b/t/rack/app.ru new file mode 100644 index 0000000000..6a4323e186 --- /dev/null +++ b/t/rack/app.ru @@ -0,0 +1,9 @@ +class App + + def call(environ) + [200, {'Content-Type' => 'text/html'}, ['Hello']] + end + +end + +run App.new diff --git a/t/runner b/t/runner index 42d6393343..b59966b5d4 100755 --- a/t/runner +++ b/t/runner @@ -21,7 +21,7 @@ import unittest TESTS_DIR = os.path.dirname(__file__) UWSGI_BINARY = os.getenv("UWSGI_BINARY", os.path.join(TESTS_DIR, "..", "uwsgi")) -UWSGI_PLUGINS = os.getenv("UWSGI_PLUGINS", "all").split(" ") +UWSGI_PLUGINS = os.getenv("UWSGI_PLUGINS_TEST", "all").split(" ") UWSGI_ADDR = "127.0.0.1" UWSGI_PORT = 8000 UWSGI_HTTP = f"{UWSGI_ADDR}:{UWSGI_PORT}" @@ -83,19 +83,23 @@ class UwsgiTest(unittest.TestCase): result = self._outcome.result ok = not (result.errors + result.failures) - self.testserver.send_signal(signal.SIGTERM) - if not ok: - print(self.testserver.stdout.read(), file=sys.stderr) + if hasattr(self, "testserver"): + self.testserver.send_signal(signal.SIGTERM) + if not ok: + print(self.testserver.stdout.read(), file=sys.stderr) - self.testserver.wait() - self.testserver.stdout.close() + self.testserver.wait() + self.testserver.stdout.close() + + def assert_GET_body(self, url_path, body_expected): + with requests.get(f"http://{UWSGI_HTTP}{url_path}") as r: + self.assertEqual(r.text, body_expected) - @unittest.skipUnless(*plugins_available(["python"])) def test_static_expires(self): self.start_listen_server( [ "--plugin", - "python", # provide a request plugin + "notfound", os.path.join(TESTS_DIR, "static", "config.ini"), ] ) @@ -103,6 +107,44 @@ class UwsgiTest(unittest.TestCase): with requests.get(f"http://{UWSGI_HTTP}/foobar/config.ini") as r: self.assertTrue("Expires" in r.headers) + @unittest.skipUnless(*plugins_available(["python"])) + def test_mountpoints(self): + self.start_listen_server( + [ + "--plugin", + "python", + os.path.join( + TESTS_DIR, + "python", + "manage_script_name", + "manage_script_name_test.ini", + ), + ] + ) + + mps = {"/foo", "/foobis/", "/footris/"} + + for mp in mps: + # Requests to /foo should kick-in the managed script name. + self.assert_GET_body(mp, mp) + + ends = mp.endswith("/") + + # And equally requests to /foo/ + self.assert_GET_body(f"{mp}/" if not ends else f"{mp}"[:-1], mp) + + # Or correct requests (/foo/resource) + self.assert_GET_body(f"{mp}/resource" if not ends else f"{mp}resource", mp) + + mps = { + "/fooanything", + "/foobisis/", + "/foofighters", + } + + for mp in mps: + self.assert_GET_body(mp, "") + @unittest.skipUnless(*plugins_available(["python"])) def test_python3_helloworld(self): self.start_listen_server( @@ -114,8 +156,7 @@ class UwsgiTest(unittest.TestCase): ] ) - with requests.get(f"http://{UWSGI_HTTP}/") as r: - self.assertEqual(r.text, "Hello World") + self.assert_GET_body("/", "Hello World") @unittest.skipUnless(*plugins_available(["pypy"])) def test_pypy3_helloworld(self): @@ -125,8 +166,7 @@ class UwsgiTest(unittest.TestCase): ] ) - with requests.get(f"http://{UWSGI_HTTP}/") as r: - self.assertEqual(r.text, "Hello World") + self.assert_GET_body("/", "Hello World") @unittest.skipUnless(*plugins_available(["php"])) def test_php_session(self): @@ -136,8 +176,82 @@ class UwsgiTest(unittest.TestCase): ] ) - with requests.get(f"http://{UWSGI_HTTP}/test.php") as r: - self.assertEqual(r.text, "PASS\n") + self.assert_GET_body("/test.php", "PASS\n") + + @unittest.skipUnless(*plugins_available(["jvm"])) + def test_jvm_hellworld(self): + classpath = ":".join( + [ + "/usr/share/java/uwsgi.jar", + os.path.join(TESTS_DIR, "java"), + os.path.join(TESTS_DIR, "..", "plugins", "jvm"), + ] + ) + + subprocess.call( + [ + "javac", + "-classpath", + classpath, + os.path.join(TESTS_DIR, "java", "rpc.java"), + ] + ) + + self.start_listen_server( + [ + "--need-app=0", + "--plugins", + "0:jvm,jwsgi", + "--jvm-classpath", + classpath, + "--jwsgi", + "rpc:application", + ] + ) + + self.assert_GET_body("/", "