Skip to content

Commit 4eec516

Browse files
committed
feat: add CI testing workflow and Docker test suite
- Add GitHub Actions workflow for running tests - Add docker-compose test configuration - Add Python test suite with HTTP stats, MTProto port, and Telethon tests - Add TESTING.md documentation - Fix secret generation in Dockerfile (use xxd from vim-common) - Use non-privileged port 8443 in CI to avoid permission issues Fixes #21
1 parent 34b6e12 commit 4eec516

File tree

17 files changed

+423
-23
lines changed

17 files changed

+423
-23
lines changed

.github/workflows/test.yml

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ "master" ]
6+
pull_request:
7+
branches: [ "master" ]
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v3
14+
15+
- name: Build and Run Tests
16+
env:
17+
MTPROXY_SECRET: ${{ secrets.MTPROXY_SECRET }}
18+
run: |
19+
if [ -z "$MTPROXY_SECRET" ]; then
20+
export MTPROXY_SECRET=$(head -c 16 /dev/urandom | xxd -ps)
21+
echo "Generated random MTPROXY_SECRET for testing"
22+
fi
23+
24+
make test
25+
26+
test-direct:
27+
runs-on: ubuntu-latest
28+
steps:
29+
- uses: actions/checkout@v3
30+
31+
- name: Install Dependencies
32+
run: |
33+
sudo apt-get update
34+
sudo apt-get install -y build-essential libssl-dev zlib1g-dev git curl vim-common python3 python3-pip python3-venv netcat-openbsd
35+
python3 -m venv .venv
36+
source .venv/bin/activate
37+
pip install requests
38+
39+
- name: Build MTProxy
40+
run: |
41+
make clean && make -j$(nproc)
42+
43+
- name: Setup and Run Proxy
44+
run: |
45+
# Debug: Check connectivity to Telegram DC
46+
echo "Checking connectivity to Telegram DC (149.154.175.50:443)..."
47+
nc -zv 149.154.175.50 443 || echo "Failed to connect to Telegram DC 149.154.175.50:443"
48+
49+
mkdir -p mtproxy-run
50+
cp objs/bin/mtproto-proxy mtproxy-run/
51+
52+
cd mtproxy-run
53+
54+
# Download config/secret
55+
curl -s https://core.telegram.org/getProxySecret -o proxy-secret
56+
curl -s https://core.telegram.org/getProxyConfig -o proxy-multi.conf
57+
58+
# Generate a random secret for testing using xxd (from vim-common)
59+
SECRET=$(head -c 16 /dev/urandom | xxd -ps)
60+
echo "Using secret: $SECRET"
61+
62+
# Start proxy in background (use port 8443 to avoid permission issues)
63+
./mtproto-proxy -u nobody -p 8888 -H 8443 -S $SECRET --http-stats --aes-pwd proxy-secret proxy-multi.conf -M 1 &
64+
65+
# Export SECRET for the test step
66+
echo "MTPROXY_SECRET=$SECRET" >> $GITHUB_ENV
67+
68+
# Wait for it to start
69+
sleep 5
70+
71+
- name: Run Python Tests
72+
run: |
73+
source .venv/bin/activate
74+
export MTPROXY_HOST=localhost
75+
export MTPROXY_PORT=8443
76+
python3 tests/test_proxy.py

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
objs
22
dep
3-
.idea/
3+
.idea
4+
proxy-multi.conf
5+
proxy-secret

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,22 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## 2025-11-28
6+
7+
- Fixed high CPU usage (Issue #100):
8+
- Optimized `epoll_wait` timeout in `net/net-events.c` to be dynamic based on pending timers.
9+
- Corrected `epoll_timeout` handling in `engine/engine.c` and `mtproto/mtproto-proxy.c`.
10+
- Fixed Docker startup issue (Issue #21):
11+
- Added `vim-common` to `Dockerfile` to provide `xxd` for secret generation.
12+
- Added comprehensive test suite:
13+
- Added `tests/` directory with Python-based tests using `telethon`.
14+
- Added `make test` target for running tests in Docker.
15+
- Added `TESTING.md` documentation.
16+
- Added GitHub Actions workflow for automated testing.
17+
- Build fixes:
18+
- Added missing headers (`<x86intrin.h>`) in `engine/engine-rpc.h`.
19+
- Suppressed array-bounds warnings for specific files.
20+
521
## 2025-09-19
622

723
- Added IPv6 usage documentation to `README.md`:

Dockerfile

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
# Use Ubuntu as base image for building
2-
FROM ubuntu:22.04 AS builder
1+
# Use Ubuntu as base image for building (force x86_64 for intrinsics support)
2+
FROM --platform=linux/amd64 ubuntu:22.04 AS builder
33

44
# Install build dependencies
55
RUN apt-get update && apt-get install -y \
@@ -16,17 +16,18 @@ WORKDIR /src
1616
COPY . .
1717

1818
# Build the application
19-
RUN make clean && make
19+
RUN make clean && make -j$(nproc)
2020

21-
# Runtime image
22-
FROM ubuntu:22.04
21+
# Runtime image (must match builder architecture)
22+
FROM --platform=linux/amd64 ubuntu:22.04
2323

2424
# Install runtime dependencies
2525
RUN apt-get update && apt-get install -y \
2626
libssl3 \
2727
zlib1g \
2828
curl \
2929
ca-certificates \
30+
vim-common \
3031
&& rm -rf /var/lib/apt/lists/*
3132

3233
# Create user for running the proxy
@@ -74,9 +75,22 @@ STATS_PORT=\${STATS_PORT:-8888}
7475
WORKERS=\${WORKERS:-1}
7576
PROXY_TAG=\${PROXY_TAG:-}
7677
RANDOM_PADDING=\${RANDOM_PADDING:-}
78+
# Max connections - lower value avoids rlimit issues in containers
79+
MAX_CONNECTIONS=\${MAX_CONNECTIONS:-60000}
80+
81+
# Detect container-local IPv4 for NAT (used when EXTERNAL_IP is provided).
82+
LOCAL_IP=\$(grep -vE '(local|ip6|^fd)' /etc/hosts | awk 'NR==1 {print \$1}')
83+
84+
# Optional public IPv4 address to advertise to Telegram DCs; pass via -e EXTERNAL_IP=1.2.3.4
85+
EXTERNAL_IP=\${EXTERNAL_IP:-}
86+
87+
NAT_INFO_ARGS=""
88+
if [ -n "\$EXTERNAL_IP" ] && [ -n "\$LOCAL_IP" ]; then
89+
NAT_INFO_ARGS="--nat-info \$LOCAL_IP:\$EXTERNAL_IP"
90+
fi
7791

7892
# Build command
79-
CMD="./mtproto-proxy -u mtproxy -p \$STATS_PORT -H \$PORT -S \$SECRET --http-stats"
93+
CMD="./mtproto-proxy -p \$STATS_PORT -H \$PORT -S \$SECRET -c \$MAX_CONNECTIONS --http-stats \$NAT_INFO_ARGS"
8094

8195
if [ -n "\$PROXY_TAG" ]; then
8296
CMD="\$CMD -P \$PROXY_TAG"
@@ -86,7 +100,7 @@ if [ "\$RANDOM_PADDING" = "true" ]; then
86100
CMD="\$CMD -R"
87101
fi
88102

89-
CMD="\$CMD --aes-pwd proxy-secret proxy-multi.conf -M \$WORKERS"
103+
CMD="\$CMD --aes-pwd proxy-secret proxy-multi.conf -M \$WORKERS -u mtproxy \$@"
90104

91105
echo "Starting MTProxy with command: \$CMD"
92106
exec \$CMD

Makefile

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ endif
1616
HOST_ARCH := $(shell arch)
1717

1818
# Default CFLAGS and LDFLAGS
19-
COMMON_CFLAGS := -O3 -std=gnu11 -Wall -fno-strict-aliasing -fno-strict-overflow -fwrapv -DAES=1 -DCOMMIT=\"${COMMIT}\" -D_GNU_SOURCE=1 -D_FILE_OFFSET_BITS=64
19+
COMMON_CFLAGS := -O3 -std=gnu11 -Wall -fno-strict-aliasing -fno-strict-overflow -fwrapv -DAES=1 -DCOMMIT=\"${COMMIT}\" -D_GNU_SOURCE=1 -D_FILE_OFFSET_BITS=64 -Wno-array-bounds -Wno-implicit-function-declaration
2020
COMMON_LDFLAGS := -ggdb -rdynamic -lm -lrt -lcrypto -lz -lpthread
2121

2222
# Architecture-specific CFLAGS
@@ -129,5 +129,16 @@ docker-run-help-amd64: docker-image-amd64
129129
${DOCKER} run --rm --platform ${DOCKER_PLATFORM} --entrypoint /opt/mtproxy/mtproto-proxy ${DOCKER_TEST_IMAGE} 2>&1 | grep -q "Invoking engine"
130130

131131
tests: docker-run-help-amd64
132-
@echo "Tests passed: amd64 image builds and binary starts (--help)."
132+
@echo "Smoke test passed: amd64 image builds and binary starts (--help)."
133+
134+
test:
135+
@# Generate secret if not provided
136+
@if [ -z "$$MTPROXY_SECRET" ]; then \
137+
export MTPROXY_SECRET=$$(head -c 16 /dev/urandom | xxd -ps); \
138+
echo "Generated MTPROXY_SECRET: $$MTPROXY_SECRET"; \
139+
fi && \
140+
export MTPROXY_SECRET=$${MTPROXY_SECRET:-$$(head -c 16 /dev/urandom | xxd -ps)} && \
141+
echo "Using secret: $$MTPROXY_SECRET" && \
142+
timeout 1200s docker compose -f tests/docker-compose.test.yml up --build --exit-code-from tester || \
143+
(echo "Test timed out or failed"; docker compose -f tests/docker-compose.test.yml down; exit 1)
133144

README.md

Lines changed: 84 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,18 @@ make && cd objs/bin
5757

5858
If the build has failed, you should run `make clean` before building it again.
5959

60+
## Testing
61+
62+
This repository includes a comprehensive test suite. For detailed instructions, see [TESTING.md](TESTING.md).
63+
64+
To run the tests using Docker:
65+
66+
```bash
67+
# Export environment variables (see TESTING.md)
68+
export MTPROXY_SECRET=...
69+
make test
70+
```
71+
6072
## Running
6173
1. Obtain a secret, used to connect to telegram servers.
6274
```bash
@@ -246,9 +258,37 @@ systemctl enable MTProxy.service
246258

247259
## Docker
248260

249-
### Using Pre-built Docker Image
261+
### Quick Start
262+
263+
The simplest way to run MTProxy - no configuration needed:
264+
265+
```bash
266+
docker run -d \
267+
--name mtproxy \
268+
-p 443:443 \
269+
-p 8888:8888 \
270+
--restart unless-stopped \
271+
--platform linux/amd64 \
272+
ghcr.io/getpagespeed/mtproxy:latest
273+
```
274+
275+
The container automatically:
276+
- Downloads the latest proxy configuration from Telegram
277+
- Generates a random secret if none is provided
278+
- Starts the proxy on port 443
279+
280+
**Finding Your Auto-Generated Secret:**
250281

251-
The easiest way to run MTProxy is using our pre-built Docker image from GitHub Container Registry:
282+
```bash
283+
docker logs mtproxy 2>&1 | grep "Generated secret"
284+
# Output: Generated secret: abc123def456...
285+
```
286+
287+
Use this secret to configure your Telegram client.
288+
289+
### Using Pre-built Docker Image (Advanced)
290+
291+
For more control, specify environment variables:
252292

253293
```bash
254294
docker run -d \
@@ -272,8 +312,9 @@ docker run -d \
272312
- `PORT`: Port for client connections (default: 443)
273313
- `STATS_PORT`: Port for statistics endpoint (default: 8888)
274314
- `WORKERS`: Number of worker processes (default: 1)
275-
- `PROXY_TAG`: Proxy tag from [@MTProxybot](https://t.me/MTProxybot)
315+
- `PROXY_TAG`: Proxy tag from [@MTProxybot](https://t.me/MTProxybot) (optional, for channel promotion)
276316
- `RANDOM_PADDING`: Enable random padding only mode (true/false, default: false)
317+
- `EXTERNAL_IP`: Your public IP address for NAT environments (optional)
277318

278319
#### Getting Statistics
279320

@@ -283,16 +324,46 @@ curl http://localhost:8888/stats
283324

284325
### Using Docker Compose
285326

286-
Create a `.env` file:
327+
The simplest Docker Compose setup (create `docker-compose.yml`):
328+
329+
```yaml
330+
services:
331+
mtproxy:
332+
image: ghcr.io/getpagespeed/mtproxy:latest
333+
platform: linux/amd64
334+
ports:
335+
- "443:443"
336+
- "8888:8888"
337+
restart: unless-stopped
338+
```
339+
340+
Then run:
341+
```bash
342+
docker-compose up -d
343+
docker-compose logs mtproxy | grep "Generated secret"
344+
```
345+
346+
For custom configuration, create a `.env` file:
287347
```bash
288348
SECRET=your_secret_here
289349
PROXY_TAG=your_proxy_tag_here
290350
RANDOM_PADDING=false
291351
```
292352

293-
Then run:
294-
```bash
295-
docker-compose up -d
353+
And reference it in your `docker-compose.yml`:
354+
```yaml
355+
services:
356+
mtproxy:
357+
image: ghcr.io/getpagespeed/mtproxy:latest
358+
platform: linux/amd64
359+
ports:
360+
- "443:443"
361+
- "8888:8888"
362+
environment:
363+
- SECRET=${SECRET}
364+
- PROXY_TAG=${PROXY_TAG}
365+
- RANDOM_PADDING=${RANDOM_PADDING}
366+
restart: unless-stopped
296367
```
297368
298369
### Building Your Own Image
@@ -305,10 +376,15 @@ docker run -d \
305376
--name mtproxy \
306377
-p 443:443 \
307378
-p 8888:8888 \
308-
-e SECRET=your_secret_here \
379+
--platform linux/amd64 \
309380
mtproxy
310381
```
311382

383+
Check the logs to find your auto-generated secret:
384+
```bash
385+
docker logs mtproxy 2>&1 | grep "Generated secret"
386+
```
387+
312388
### Health Check
313389

314390
The Docker container includes a health check that monitors the statistics endpoint. You can check the container health with:

0 commit comments

Comments
 (0)