Skip to content
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

Backports for 2.0.26 #2647

Merged
merged 8 commits into from
Jun 1, 2024
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
44 changes: 30 additions & 14 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,38 @@ on:
branches: [ master, uwsgi-2.0 ]

jobs:
python:

unittest:
runs-on: ubuntu-20.04
steps:
- name: Install dependencies
run: |
sudo apt update -qq
sudo apt install --no-install-recommends -qqyf \
libpcre2-dev libjansson-dev libcap2-dev \
check
- uses: actions/checkout@v4
- name: Run unit tests
run: make unittests

test:
runs-on: ubuntu-20.04
steps:
- name: Install dependencies
run: |
sudo apt update -qq
sudo apt install --no-install-recommends -qqyf \
libpcre2-dev libjansson-dev libcap2-dev
- uses: actions/checkout@v4
- name: Run integration tests
run: make all tests

python:
runs-on: ubuntu-20.04
strategy:
matrix:
python-version: ["2.7", "3.6", "3.7", "3.8", "3.9", "3.10", "3.11", "3.12"]
test-suite: [unittest, python, deadlocks]
test-suite: [python, deadlocks]
steps:
- name: Add deadnakes ppa
run: sudo add-apt-repository ppa:deadsnakes/ppa -y
Expand All @@ -22,34 +47,27 @@ jobs:
sudo apt update -qq
sudo apt install --no-install-recommends -qqyf python${{ matrix.python-version }}-dev \
libpcre2-dev libjansson-dev libcap2-dev \
curl check
curl
- name: Install distutils
if: contains(fromJson('["3.6","3.7","3.8","3.9","3.10","3.11","3.12"]'), matrix.python-version)
run: |
sudo apt install --no-install-recommends -qqyf python${{ matrix.python-version }}-distutils \
- uses: actions/checkout@v4
- name: Run unit tests
if: matrix.test-suite == 'unittest'
run: make tests
- name: Build uWSGI binary
if: matrix.test-suite != 'unittest'
run: make
- name: Build python${{ matrix.python-version }} plugin
if: matrix.test-suite != 'unittest'
run: |
PYTHON_VERSION=${{ matrix.python-version }}
PYTHON_VERSION=python${PYTHON_VERSION//.}
/usr/bin/python${{ matrix.python-version }} -V
/usr/bin/python${{ matrix.python-version }} uwsgiconfig.py --plugin plugins/python base $PYTHON_VERSION
- name: run smoke tests
if: matrix.test-suite != 'unittest'
run: |
PYTHON_VERSION=${{ matrix.python-version }}
PYTHON_VERSION=python${PYTHON_VERSION//.}
./tests/gh-${{ matrix.test-suite }}.sh ${PYTHON_VERSION}

rack:

runs-on: ubuntu-20.04
strategy:
matrix:
Expand All @@ -59,11 +77,9 @@ jobs:
run: |
sudo apt update -qq
sudo apt install --no-install-recommends -qqyf python3-dev \
libpcre3-dev libjansson-dev libcap2-dev ruby2.7-dev \
curl check
libpcre2-dev libjansson-dev libcap2-dev ruby2.7-dev \
curl
- uses: actions/checkout@v4
- name: Run unit tests
run: make tests
- name: Build uWSGI binary
run: make
- name: Build rack plugin
Expand Down
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,20 @@ all:

clean:
$(PYTHON) uwsgiconfig.py --clean
cd unittest && make clean

check:
$(PYTHON) uwsgiconfig.py --check

plugin.%:
$(PYTHON) uwsgiconfig.py --plugin plugins/$* $(PROFILE)

unittests:
$(PYTHON) uwsgiconfig.py --build unittest
cd unittest && make test

tests:
$(PYTHON) t/runner

%:
$(PYTHON) uwsgiconfig.py --build $@
6 changes: 6 additions & 0 deletions apache2/mod_proxy_uwsgi.c
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,12 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_
return HTTP_BAD_GATEWAY;
}

/* T-E wins over C-L */
if (apr_table_get(r->headers_out, "Transfer-Encoding")) {
apr_table_unset(r->headers_out, "Content-Length");
backend->close = 1;
}

if ((buf = apr_table_get(r->headers_out, "Content-Type"))) {
ap_set_content_type(r, apr_pstrdup(r->pool, buf));
}
Expand Down
6 changes: 6 additions & 0 deletions buildconf/unittest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[uwsgi]
inherit = base
bin_name = libuwsgi.a
embedded_plugins = null
as_shared_library = static
check = true
4 changes: 2 additions & 2 deletions core/regexp.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ int uwsgi_regexp_build(char *re, uwsgi_pcre ** pattern) {

#ifdef UWSGI_PCRE2
int errnbr;
long unsigned int erroff;
size_t erroff;

*pattern = pcre2_compile((const unsigned char *) re, PCRE2_ZERO_TERMINATED, 0, &errnbr, &erroff, NULL);
#else
Expand Down Expand Up @@ -69,7 +69,7 @@ int uwsgi_regexp_build(char *re, uwsgi_pcre ** pattern) {

int uwsgi_regexp_match(uwsgi_pcre *pattern, const char *subject, int length) {
#ifdef UWSGI_PCRE2
return pcre2_match(pattern, (const unsigned char *)subject, length, 0, 0, NULL, NULL);
return uwsgi_regexp_match_ovec(pattern, subject, length, NULL, 0);
#else
return pcre_exec((const pcre *) pattern->p, (const pcre_extra *) pattern->extra, subject, length, 0, 0, NULL, 0);
#endif
Expand Down
7 changes: 0 additions & 7 deletions core/uwsgi.c
Original file line number Diff line number Diff line change
Expand Up @@ -3835,13 +3835,6 @@ void uwsgi_init_all_apps() {
if (uwsgi.need_app) {
if (!uwsgi.lazy)
uwsgi_log("*** no app loaded. GAME OVER ***\n");
if (uwsgi.lazy_apps) {
if (uwsgi.master_process) {
if (kill(uwsgi.workers[0].pid, SIGINT)) {
uwsgi_error("kill()");
}
}
}
exit(UWSGI_FAILED_APP_CODE);
}
else {
Expand Down
82 changes: 82 additions & 0 deletions t/runner
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#!/usr/bin/python3


import os
import requests
import signal
import socket
import subprocess
import time
import unittest


TESTS_DIR = os.path.dirname(__file__)
UWSGI_BINARY = os.getenv("UWSGI_BINARY", os.path.join(TESTS_DIR, "..", "uwsgi"))
UWSGI_ADDR = "127.0.0.1"
UWSGI_PORT = 8000
UWSGI_HTTP = f"{UWSGI_ADDR}:{UWSGI_PORT}"


class BaseTest:
"""
Container class to avoid base test being run
"""

class UwsgiServerTest(unittest.TestCase):
"""
Test case with a server instance available on a socket for requests
"""

@classmethod
def uwsgi_ready(cls):
try:
s = socket.socket()
s.connect(
(
UWSGI_ADDR,
UWSGI_PORT,
)
)
except socket.error:
return False
else:
return True
finally:
s.close()

@classmethod
def setUpClass(cls):
# launch server
cls.testserver = subprocess.Popen(
[UWSGI_BINARY, "--http-socket", UWSGI_HTTP] + cls.ARGS
)

# ensure server is ready
retries = 10
while not cls.uwsgi_ready() and retries > 0:
time.sleep(0.1)
retries = retries - 1
if retries == 0:
raise RuntimeError("uwsgi test server is not available")

@classmethod
def tearDownClass(cls):
cls.testserver.send_signal(signal.SIGTERM)
cls.testserver.wait()


class StaticTest(BaseTest.UwsgiServerTest):

ARGS = [
"--plugin",
"python3", # provide a request plugin if no embedded request plugin
os.path.join(TESTS_DIR, "static", "config.ini"),
]

def test_static_expires(self):
with requests.get(f"http://{UWSGI_HTTP}/foobar/config.ini") as r:
self.assertTrue("Expires" in r.headers)


if __name__ == "__main__":
unittest.main()
4 changes: 4 additions & 0 deletions t/static/config.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[uwsgi]
need-app = False
static-map = /foobar=t/static
static-expires-uri = ^/foobar/ 315360000
28 changes: 28 additions & 0 deletions unittest/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

CFLAGS = $(shell pkg-config --cflags check)
CFLAGS += -DUWSGI_PCRE2
LDFLAGS = $(shell pkg-config --libs check)
LDFLAGS += -ldl -lz
LDFLAGS += $(shell xml2-config --libs)
LDFLAGS += $(shell pkg-config --libs openssl)
LDFLAGS += $(shell pcre2-config --libs8)
LDFLAGS += $(shell pkg-config --libs jansson)

UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Linux)
LDFLAGS += -lcap
endif


objects = check_core check_regexp

all: $(objects)

$(objects): %: %.c ../libuwsgi.a
$(CC) $(CFLAGS) -o $@ $< ../libuwsgi.a $(LDFLAGS)

test: all
@for file in $(objects); do ./$$file; done

clean:
rm -f $(objects)
108 changes: 108 additions & 0 deletions unittest/check_core.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#include <check.h>
#include "../uwsgi.h"


START_TEST(test_uwsgi_strncmp)
{
int result;
result = uwsgi_strncmp("test", 4, "test", 4);
ck_assert(result == 0);

result = uwsgi_strncmp("test", 4, "tes", 3);
ck_assert(result == 1);

result = uwsgi_strncmp("tes", 3, "test", 4);
ck_assert(result == 1);

result = uwsgi_strncmp("aaa", 3, "bbb", 3);
ck_assert_msg(result < 0, "result: %d", result);

result = uwsgi_strncmp("bbb", 3, "aaa", 3);
ck_assert_msg(result > 0, "result: %d", result);
}
END_TEST

Suite *check_core_strings(void)
{
Suite *s = suite_create("uwsgi strings");
TCase *tc = tcase_create("strings");

suite_add_tcase(s, tc);
tcase_add_test(tc, test_uwsgi_strncmp);
return s;
}

START_TEST(test_uwsgi_opt_set_int)
{
int result;
uwsgi_opt_set_int("", "true", &result);
ck_assert(result == 0);

uwsgi_opt_set_int("", "false", &result);
ck_assert(result == 0);

uwsgi_opt_set_int("", "0", &result);
ck_assert(result == 0);

uwsgi_opt_set_int("", "60", &result);
ck_assert(result == 60);

// When used with "optional_argument", value will be passed as NULL
uwsgi_opt_set_int("", NULL, &result);
ck_assert(result == 1);
}
END_TEST

Suite *check_core_opt_parsing(void)
{
Suite *s = suite_create("uwsgi opt parsing");
TCase *tc = tcase_create("opt_parsing");

suite_add_tcase(s, tc);
tcase_add_test(tc, test_uwsgi_opt_set_int);
return s;
}

START_TEST(test_uwsgi_cron_task_needs_execution_handles_weekday_7_as_sunday)
{
int result;
struct tm *t;
time_t now;

now = time(NULL);
t = localtime(&now);
t->tm_wday= 0;

result = uwsgi_cron_task_needs_execution(t, -1, -1, -1, -1, 0);
ck_assert(result == 1);

result = uwsgi_cron_task_needs_execution(t, -1, -1, -1, -1, 7);
ck_assert(result == 1);

result = uwsgi_cron_task_needs_execution(t, -1, -1, -1, -1, 1);
ck_assert(result == 0);
}
END_TEST

Suite *check_core_cron(void)
{
Suite *s = suite_create("uwsgi cron");
TCase *tc = tcase_create("cron");

suite_add_tcase(s, tc);
tcase_add_test(tc, test_uwsgi_cron_task_needs_execution_handles_weekday_7_as_sunday);
return s;
}

int main(void)
{
int nf;
SRunner *r = srunner_create(check_core_strings());
srunner_add_suite(r, check_core_opt_parsing());
srunner_add_suite(r, check_core_cron());
srunner_run_all(r, CK_NORMAL);
nf = srunner_ntests_failed(r);
srunner_free(r);
return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}

Loading