Skip to content

Commit fd57897

Browse files
committed
Add tests and github actions workflow
1 parent 1349fc2 commit fd57897

File tree

10 files changed

+223
-20
lines changed

10 files changed

+223
-20
lines changed

.github/workflows/test.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
name: Test
2+
3+
on: [pull_request]
4+
5+
jobs:
6+
test:
7+
runs-on: ubuntu-latest
8+
9+
steps:
10+
- uses: actions/checkout@v2
11+
- name: Unit
12+
run: |
13+
make test
14+
- name: E2E
15+
run: |
16+
make test_e2e

Makefile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.PHONY: test test_e2e
2+
3+
test:
4+
docker-compose build test && docker-compose run --rm test
5+
docker-compose down -t 0
6+
7+
test_e2e:
8+
docker-compose build test_e2e && docker-compose run --rm test_e2e
9+
docker-compose down -t 0

README.md

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
[![Travis Build Status](https://travis-ci.org/refinitiv/ngx_http_websocket_stat_module.svg?branch=master)](https://travis-ci.org/refinitiv/ngx_http_websocket_stat_module.svg?branch=master)
1+
![Tests](https://github.com/github/docs/actions/workflows/test.yml/badge.svg)
22

33

44
# NGINX module websocket connection and traffic statistics
@@ -9,21 +9,20 @@ Nginx module developed for logging and displaying statistic of websocket proxy c
99

1010
1. Configure nginx adding this module with or build this module as a dynamic module:
1111
```sh
12-
./configure (...) --add-module=./ngx_http_websocket_stat_module
12+
./configure (...) --add-module=./src/ngx_http_websocket_stat_module
1313
# or
14-
./configure (...) --add-dynamic-module=./ngx_http_websocket_stat_module && make modules
14+
./configure (...) --add-dynamic-module=./src/ngx_http_websocket_stat_module && make modules
1515
```
1616

1717
## Usage
1818

1919
To enable websocket frames logging specify `log_enabled on` and `ws_log_format` in server section of nginx config file. Additionally, specify `ws_log` to override the log file, which is used to log ws frames.
2020

2121
To customize connection open and close log messages use "open" and "close" parameter for ws_log_format directive.
22-
To log only when the full message is received/sent use "message" parameter for ws_log_format directive.
22+
To log only when the full message is received/sent use "server"/"client" parameters for ws_log_format directive.
2323

2424
To set maximum single connection lifetime use ws_conn_age parameter. Argument is time given in nginx time format (e.g. 1s, 1m 1h and so on). When connection's lifetime is exceeding specified value there is close websocket packet with 4001 error code generated and connection is closed.
2525

26-
2726
Here is a list of variables you can use in log format string:
2827

2928
* $ws_opcode - websocket packet opcode. Look into https://tools.ietf.org/html/rfc6455 Section 5.2, Base Framing Protocol.
@@ -42,21 +41,7 @@ Here is a list of variables you can use in log format string:
4241
* $server_port - Server's port
4342
* $upstream_addr - websocket backend address
4443

45-
## Example of configuration
46-
47-
```
48-
49-
server
50-
{
51-
ws_log <path/to/logfile>;
52-
ws_log_format "$time_local: packet of type $ws_opcode received from $ws_packet_source, packet size is $ws_payload_size";
53-
ws_log_format open "$time_local: Connection opened";
54-
ws_log_format close "$time_local: Connection closed";
55-
ws_conn_age 12h;
56-
...
57-
}
58-
59-
```
44+
See [nginx sample configuraion](docker/nginx.conf).
6045

6146
## Copyright
6247

docker-compose.yaml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
version: "3.6"
2+
services:
3+
nginx:
4+
command: nginx -g "daemon off;"
5+
build:
6+
context: .
7+
dockerfile: ./docker/Dockerfile.nginx
8+
volumes:
9+
- ./docker/nginx.conf:/etc/nginx/nginx.conf
10+
- logs:/var/log/nginx
11+
12+
test_e2e:
13+
build:
14+
context: .
15+
dockerfile: ./docker/Dockerfile.e2e
16+
environment:
17+
- ENDPOINT=nginx
18+
- LOG_FILE_PATH=/var/log/nginx/ws.log
19+
volumes:
20+
- logs:/var/log/nginx
21+
depends_on:
22+
- nginx
23+
24+
test:
25+
build:
26+
context: .
27+
dockerfile: ./docker/Dockerfile.unit
28+
29+
volumes:
30+
logs:

docker/Dockerfile.e2e

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
FROM rust:alpine3.13
2+
3+
USER root
4+
5+
RUN apk add --no-cache musl-dev && cargo install websocat
6+
7+
COPY ./docker/test_e2e.sh /usr/local/bin/test_e2e
8+
RUN chmod +x /usr/local/bin/test_e2e
9+
10+
CMD ["test_e2e"]

docker/Dockerfile.nginx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
FROM k8s.gcr.io/ingress-nginx/controller:v0.44.0 as builder
2+
3+
USER root
4+
5+
WORKDIR /tmp
6+
7+
RUN apk add git openssl-dev pcre-dev zlib-dev libc-dev gcc make
8+
RUN NGINX_VERSION=$(nginx -v 2>&1 | sed 's/nginx version: nginx\///') && \
9+
wget -qO- https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz | tar xvz && \
10+
mv nginx-${NGINX_VERSION} nginx
11+
COPY ./src /tmp/ngx_http_websocket_stat_module
12+
RUN cd ./nginx && \
13+
./configure --with-compat \
14+
--add-dynamic-module=../ngx_http_websocket_stat_module && \
15+
make modules
16+
17+
FROM k8s.gcr.io/ingress-nginx/controller:v0.44.0
18+
COPY --from=builder /tmp/nginx/objs/ngx_http_websocket_stat_module.so /etc/nginx/modules/

docker/Dockerfile.unit

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
FROM alpine:3.10
2+
3+
USER root
4+
5+
RUN apk add gcc check-dev musl-dev
6+
7+
COPY ./src /tmp/ngx_http_websocket_stat_format/src
8+
COPY ./tests /tmp/ngx_http_websocket_stat_format/tests
9+
10+
WORKDIR /tmp/ngx_http_websocket_stat_format
11+
12+
ENV SRC_DIR="./src" \
13+
DIST_DIR="./dist" \
14+
TEST_DIR="./tests" \
15+
TEST_DIST_DIR="./tests/dist"
16+
17+
RUN mkdir ${DIST_DIR} ${TEST_DIST_DIR} && \
18+
gcc -g -DTEST -g -c ${SRC_DIR}/ngx_http_websocket_stat_format.c -o ${DIST_DIR}/ngx_http_websocket_stat_format.o && \
19+
gcc -g -DTEST ${TEST_DIR}/test_format.c -c -o ${TEST_DIST_DIR}/test_format.o -lcheck && \
20+
gcc -g -DTEST ${TEST_DIST_DIR}/test_format.o ${DIST_DIR}/ngx_http_websocket_stat_format.o -lcheck -lrt -o ${TEST_DIST_DIR}/test_format && \
21+
cp ${TEST_DIST_DIR}/test_format /usr/local/bin/ngx_http_websocket_stat_test && chmod +x /usr/local/bin/ngx_http_websocket_stat_test
22+
23+
CMD ["ngx_http_websocket_stat_test"]

docker/nginx.conf

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
pid /tmp/nginx.pid;
2+
3+
load_module /etc/nginx/modules/ngx_http_websocket_stat_module.so;
4+
events {}
5+
http {
6+
server {
7+
listen 0.0.0.0:80;
8+
ws_log /var/log/nginx/ws.log;
9+
ws_log_format open "OPEN";
10+
ws_log_format server "SERVER->CLIENT: $ws_message_size ($http_upgrade)";
11+
ws_log_format client "CLIENT->SERVER: $ws_message_size ($http_upgrade)";
12+
ws_log_format close "CLOSE";
13+
ws_log_enabled on;
14+
location / {
15+
proxy_buffering off;
16+
proxy_request_buffering off;
17+
proxy_pass https://echo.websocket.org;
18+
proxy_ssl_server_name on;
19+
proxy_http_version 1.1;
20+
proxy_set_header Connection "upgrade";
21+
proxy_set_header Upgrade $http_upgrade;
22+
}
23+
}
24+
}

docker/test_e2e.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/usr/bin/env sh
2+
3+
set -exo pipefail
4+
5+
> ${LOG_FILE_PATH}
6+
7+
cat <<EOF > /tmp/ws-expected.log
8+
OPEN
9+
CLIENT->SERVER: 1311 (websocket)
10+
SERVER->CLIENT: 1311 (websocket)
11+
CLOSE
12+
EOF
13+
14+
echo "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?" \
15+
| tr -d \\n \
16+
| websocat --text -1 ws://${ENDPOINT}
17+
18+
diff ${LOG_FILE_PATH} /tmp/ws-expected.log

tests/test_format.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
#include <check.h>
5+
6+
#include "../src/ngx_http_websocket_stat_format.h"
7+
8+
void
9+
test_func(ngx_http_request_t *r, void *data, char* buff, size_t size)
10+
{
11+
snprintf(buff, size, "BINGO");
12+
}
13+
14+
const template_variable variables[] = {
15+
{VAR_NAME("$ws_opcode"), sizeof("pding") - 1, test_func},
16+
{VAR_NAME("$ws_payload_size"), 10, test_func},
17+
{VAR_NAME("$ws_message_size"), 10, test_func},
18+
{VAR_NAME("$ws_packet_source"), sizeof("upstream") - 1, test_func},
19+
{VAR_NAME("$ws_conn_age"), 10, test_func},
20+
{VAR_NAME("$request"), 10, test_func},
21+
{VAR_NAME("$request_id"), 10, test_func},
22+
{VAR_NAME("$time_local"), sizeof("Mon, 23 Oct 2017 11:27:42 GMT") - 1,
23+
test_func},
24+
{NULL, 0, 0, NULL}};
25+
26+
const char *templates[][2] = {
27+
{"Some template $ws_opcode sdkj $ws_packet_source f", "Some template BINGO sdkj BINGO f"},
28+
{"Some template $ws_opcode sdkj f", "Some template BINGO sdkj f"},
29+
{"Some template f", "Some template f"},
30+
{"", ""},
31+
{"$time_local", "BINGO"},
32+
{"$time_local$ws_opcode$ws_payload_size", "BINGOBINGOBINGO"},
33+
{"$time_", "$time_"},
34+
{"$request $request_id", "BINGO BINGO"},
35+
{"$ws_message_size", "BINGO"},
36+
};
37+
38+
START_TEST (test_format_templates)
39+
{
40+
compiled_template *template_cmpl = compile_template((char *)templates[_i][0], variables, NULL);
41+
char *res = apply_template(template_cmpl, NULL, NULL);
42+
43+
ck_assert_str_eq(res, templates[_i][1]);
44+
}
45+
END_TEST
46+
47+
48+
Suite*
49+
test_format_suite (void)
50+
{
51+
Suite* s = suite_create ("Format");
52+
53+
TCase* tc_templates = tcase_create ("Templates");
54+
tcase_add_loop_test(tc_templates, test_format_templates, 0, sizeof(templates)/sizeof(templates[0]));
55+
56+
suite_add_tcase (s, tc_templates);
57+
58+
return s;
59+
}
60+
61+
int main(void)
62+
{
63+
SRunner *sr = srunner_create(test_format_suite());
64+
65+
srunner_run_all(sr, CK_ENV);
66+
int nf = srunner_ntests_failed(sr);
67+
srunner_free(sr);
68+
69+
return nf == 0 ? 0 : 1;
70+
}

0 commit comments

Comments
 (0)