Skip to content

Commit 4d097d7

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 4d097d7

File tree

16 files changed

+519
-23
lines changed

16 files changed

+519
-23
lines changed

.github/workflows/test.yml

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
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+
# Use secret if available, otherwise will be generated in run step
18+
MTPROXY_SECRET: ${{ secrets.MTPROXY_SECRET }}
19+
# Optional: Only set if secrets are provided (empty means skip telethon test)
20+
TELEGRAM_API_ID: ${{ secrets.TELEGRAM_API_ID }}
21+
TELEGRAM_API_HASH: ${{ secrets.TELEGRAM_API_HASH }}
22+
run: |
23+
if [ -z "$MTPROXY_SECRET" ]; then
24+
export MTPROXY_SECRET=$(head -c 16 /dev/urandom | xxd -ps)
25+
echo "Generated random MTPROXY_SECRET for testing"
26+
fi
27+
28+
# Run tests passing env vars
29+
make test
30+
31+
test-direct:
32+
runs-on: ubuntu-latest
33+
steps:
34+
- uses: actions/checkout@v3
35+
36+
- name: Install Dependencies
37+
run: |
38+
sudo apt-get update
39+
sudo apt-get install -y build-essential libssl-dev zlib1g-dev git curl vim-common python3 python3-pip python3-venv netcat-openbsd
40+
python3 -m venv .venv
41+
source .venv/bin/activate
42+
pip install requests telethon python-dotenv python-socks[asyncio]
43+
44+
- name: Build MTProxy
45+
run: |
46+
make clean && make -j$(nproc)
47+
48+
- name: Setup and Run Proxy
49+
run: |
50+
# Debug: Check connectivity to Telegram DC
51+
echo "Checking connectivity to Telegram DC (149.154.175.50:443)..."
52+
nc -zv 149.154.175.50 443 || echo "Failed to connect to Telegram DC 149.154.175.50:443"
53+
54+
mkdir -p mtproxy-run
55+
cp objs/bin/mtproto-proxy mtproxy-run/
56+
57+
cd mtproxy-run
58+
59+
# Download config/secret
60+
curl -s https://core.telegram.org/getProxySecret -o proxy-secret
61+
curl -s https://core.telegram.org/getProxyConfig -o proxy-multi.conf
62+
63+
# Generate a random secret for testing using xxd (from vim-common)
64+
SECRET=$(head -c 16 /dev/urandom | xxd -ps)
65+
echo "Using secret: $SECRET"
66+
67+
# Start proxy in background
68+
# Use port 8443 instead of 443 to avoid permission issues or conflicts on the runner
69+
./mtproto-proxy -u nobody -p 8888 -H 8443 -S $SECRET --http-stats --aes-pwd proxy-secret proxy-multi.conf -M 1 -v -v &
70+
71+
# Export SECRET for the test step
72+
echo "MTPROXY_SECRET=$SECRET" >> $GITHUB_ENV
73+
74+
# Wait for it to start
75+
sleep 5
76+
77+
- name: Run Python Tests
78+
env:
79+
# Session path null for CI
80+
TEST_SESSION_PATH: /dev/null
81+
TELEGRAM_API_ID: ${{ secrets.TELEGRAM_API_ID }}
82+
TELEGRAM_API_HASH: ${{ secrets.TELEGRAM_API_HASH }}
83+
run: |
84+
source .venv/bin/activate
85+
# We need to tell the test script to connect to localhost since we are not in docker-compose
86+
export MTPROXY_HOST=localhost
87+
export MTPROXY_PORT=8443
88+
python3 tests/test_proxy.py
89+

.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: 19 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
@@ -75,8 +76,19 @@ WORKERS=\${WORKERS:-1}
7576
PROXY_TAG=\${PROXY_TAG:-}
7677
RANDOM_PADDING=\${RANDOM_PADDING:-}
7778

79+
# Detect container-local IPv4 for NAT (used when EXTERNAL_IP is provided).
80+
LOCAL_IP=\$(grep -vE '(local|ip6|^fd)' /etc/hosts | awk 'NR==1 {print \$1}')
81+
82+
# Optional public IPv4 address to advertise to Telegram DCs; pass via -e EXTERNAL_IP=1.2.3.4
83+
EXTERNAL_IP=\${EXTERNAL_IP:-}
84+
85+
NAT_INFO_ARGS=""
86+
if [ -n "\$EXTERNAL_IP" ] && [ -n "\$LOCAL_IP" ]; then
87+
NAT_INFO_ARGS="--nat-info \$LOCAL_IP:\$EXTERNAL_IP"
88+
fi
89+
7890
# Build command
79-
CMD="./mtproto-proxy -u mtproxy -p \$STATS_PORT -H \$PORT -S \$SECRET --http-stats"
91+
CMD="./mtproto-proxy -p \$STATS_PORT -H \$PORT -S \$SECRET --http-stats \$NAT_INFO_ARGS"
8092

8193
if [ -n "\$PROXY_TAG" ]; then
8294
CMD="\$CMD -P \$PROXY_TAG"
@@ -86,7 +98,7 @@ if [ "\$RANDOM_PADDING" = "true" ]; then
8698
CMD="\$CMD -R"
8799
fi
88100

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

91103
echo "Starting MTProxy with command: \$CMD"
92104
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)