Skip to content
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
1 change: 1 addition & 0 deletions .ci/ubuntu/enabled_plugins
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[rabbitmq_management].
16 changes: 16 additions & 0 deletions .ci/ubuntu/gha-log-check.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/bash

set -o errexit
set -o pipefail
set -o xtrace
set -o nounset

readonly docker_name_prefix='php-amqplib'

declare -r rabbitmq_docker_name="$docker_name_prefix-rabbitmq"

if docker logs "$rabbitmq_docker_name" | grep -iF inet_error
then
echo '[ERROR] found inet_error in RabbitMQ logs' 1>&2
exit 1
fi
135 changes: 135 additions & 0 deletions .ci/ubuntu/gha-setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
#!/bin/bash

set -o errexit
set -o pipefail
set -o xtrace

script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
readonly script_dir
echo "[INFO] script_dir: '$script_dir'"

readonly docker_name_prefix='php-amqplib'
readonly docker_network_name="$docker_name_prefix-network"

if [[ ! -v GITHUB_ACTIONS ]]
then
GITHUB_ACTIONS='false'
fi

if [[ -d $GITHUB_WORKSPACE ]]
then
echo "[INFO] GITHUB_WORKSPACE is set: '$GITHUB_WORKSPACE'"
else
GITHUB_WORKSPACE="$(readlink --canonicalize-existing "$script_dir/../..")"
echo "[INFO] set GITHUB_WORKSPACE to: '$GITHUB_WORKSPACE'"
fi

if [[ $1 == '--no-toxiproxy' ]]
then
readonly run_toxiproxy='false'
else
readonly run_toxiproxy='true'
fi

if [[ $2 == 'pull' ]]
then
readonly docker_pull_args='--pull always'
else
readonly docker_pull_args=''
fi

set -o nounset

declare -r rabbitmq_docker_name="$docker_name_prefix-rabbitmq"
declare -r toxiproxy_docker_name="$docker_name_prefix-toxiproxy"

function start_toxiproxy
{
if [[ $run_toxiproxy == 'true' ]]
then
# sudo ss -4nlp
echo "[INFO] starting Toxiproxy server docker container"
docker rm --force "$toxiproxy_docker_name" 2>/dev/null || echo "[INFO] $toxiproxy_docker_name was not running"
# shellcheck disable=SC2086
docker run --detach $docker_pull_args \
--name "$toxiproxy_docker_name" \
--hostname "$toxiproxy_docker_name" \
--publish 8474:8474 \
--publish 5673:5673 \
--network "$docker_network_name" \
'ghcr.io/shopify/toxiproxy:latest'
fi
}

function start_rabbitmq
{
echo "[INFO] starting RabbitMQ server docker container"
chmod 0777 "$GITHUB_WORKSPACE/.ci/ubuntu/log"
docker rm --force "$rabbitmq_docker_name" 2>/dev/null || echo "[INFO] $rabbitmq_docker_name was not running"
# shellcheck disable=SC2086
docker run --detach $docker_pull_args \
--name "$rabbitmq_docker_name" \
--hostname "$rabbitmq_docker_name" \
--publish 5671:5671 \
--publish 5672:5672 \
--publish 15671:15671 \
--publish 15672:15672 \
--network "$docker_network_name" \
--volume "$GITHUB_WORKSPACE/.ci/ubuntu/enabled_plugins:/etc/rabbitmq/enabled_plugins" \
--volume "$GITHUB_WORKSPACE/.ci/ubuntu/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf:ro" \
--volume "$GITHUB_WORKSPACE/tests/certs:/etc/rabbitmq/certs:ro" \
--volume "$GITHUB_WORKSPACE/.ci/ubuntu/log:/var/log/rabbitmq" \
rabbitmq:management
}

function wait_rabbitmq
{
set +o errexit
set +o xtrace

declare -i count=12
while (( count > 0 )) && [[ "$(docker inspect --format='{{.State.Running}}' "$rabbitmq_docker_name")" != 'true' ]]
do
echo '[WARNING] RabbitMQ container is not yet running...'
sleep 5
(( count-- ))
done

declare -i count=12
while (( count > 0 )) && ! docker exec "$rabbitmq_docker_name" epmd -names | grep -F 'name rabbit'
do
echo '[WARNING] epmd is not reporting rabbit name just yet...'
sleep 5
(( count-- ))
done

docker exec "$rabbitmq_docker_name" rabbitmqctl await_startup

set -o errexit
set -o xtrace
}

function get_rabbitmq_id
{
local rabbitmq_docker_id
rabbitmq_docker_id="$(docker inspect --format='{{.Id}}' "$rabbitmq_docker_name")"
echo "[INFO] '$rabbitmq_docker_name' docker id is '$rabbitmq_docker_id'"
if [[ -v GITHUB_OUTPUT ]]
then
if [[ -f $GITHUB_OUTPUT ]]
then
echo "[INFO] GITHUB_OUTPUT file: '$GITHUB_OUTPUT'"
fi
echo "id=$rabbitmq_docker_id" >> "$GITHUB_OUTPUT"
fi
}

docker network create "$docker_network_name" || echo "[INFO] network '$docker_network_name' is already created"

start_toxiproxy

start_rabbitmq

wait_rabbitmq

get_rabbitmq_id
Empty file added .ci/ubuntu/log/.gitkeep
Empty file.
26 changes: 26 additions & 0 deletions .ci/ubuntu/rabbitmq.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
log.console = false
log.exchange = false
log.file = /var/log/rabbitmq/rabbitmq.log
log.file.level = info

listeners.tcp.default = 5672
listeners.ssl.default = 5671

reverse_dns_lookups = false
loopback_users.guest = true

listeners.tcp.default = 5672
listeners.ssl.default = 5671

management.tcp.port = 15672
management.ssl.port = 15671

ssl_options.certfile = /etc/rabbitmq/certs/server_certificate.pem
ssl_options.keyfile = /etc/rabbitmq/certs/server_key.pem
ssl_options.cacertfile = /etc/rabbitmq/certs/ca_certificate.pem
ssl_options.verify = verify_peer
ssl_options.fail_if_no_peer_cert = false

management.ssl.certfile = /etc/rabbitmq/certs/server_certificate.pem
management.ssl.keyfile = /etc/rabbitmq/certs/server_key.pem
management.ssl.cacertfile = /etc/rabbitmq/certs/ca_certificate.pem
46 changes: 24 additions & 22 deletions .github/workflows/phpunit.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
name: PHPUnit tests

on: [push, pull_request]
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
run:
Expand Down Expand Up @@ -41,33 +45,20 @@ jobs:
phpseclib: '^3.0'
composer: 'composer:v2'
coverage: none
services:
rabbitmq:
image: rabbitmq:3.11-management
ports:
- 5671:5671
- 5672:5672
- 15671:15671
- 15672:15672
volumes:
- ${{ github.workspace }}:/src
env:
RABBITMQ_CONFIG_FILE: /src/tests/rabbitmq.conf
proxy:
image: ghcr.io/shopify/toxiproxy:2.5.0
ports:
- 8474:8474
- 5673:5673

name: PHP ${{ matrix.php }} + phpseclib ${{ matrix.phpseclib }}
env:
TOXIPROXY_HOST: localhost
TOXIPROXY_AMQP_TARGET: rabbitmq
TOXIPROXY_AMQP_TARGET: php-amqplib-rabbitmq
TOXIPROXY_AMQP_PORT: 5673
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Start RabbitMQ and Toxiproxy
id: start-rabbitmq
run: ${{ github.workspace }}/.ci/ubuntu/gha-setup.sh

- name: Install PHP
uses: shivammathur/setup-php@v2
with:
Expand All @@ -79,9 +70,6 @@ jobs:
- name: Check PHP info
run: php tests/phpinfo.php

- name: Re-start broker service to pick up rabbitmq.conf
run: docker restart ${{ job.services.rabbitmq.id }}

- name: Composer install
run: composer require --prefer-dist --no-progress --no-suggest phpseclib/phpseclib ${{ matrix.phpseclib }}

Expand All @@ -96,6 +84,20 @@ jobs:
run: ./vendor/bin/phpunit --verbose --debug --coverage-clover=coverage.xml
if: matrix.coverage != 'none'

- name: Check for errors in RabbitMQ logs
run: ${{ github.workspace}}/.ci/ubuntu/gha-log-check.sh

- name: Maybe collect Toxiproxy logs
if: failure()
run: docker logs proxy > ${{ github.workspace }}/tests/log/toxiproxy.log

- name: Maybe upload RabbitMQ logs
if: failure()
uses: actions/upload-artifact@v4
with:
name: rabbitmq-logs-php-amqplib-${{ matrix.php }}
path: ${{ github.workspace }}/tests/log/

- name: Upload Codecov coverage
if: matrix.coverage != 'none'
uses: codecov/codecov-action@v3
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ phpDocumentor.phar
/phpcs.xml
###< squizlabs/php_codesniffer ###

.phpactor.json
.phpunit.result.cache
.phpdoc
44 changes: 34 additions & 10 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,39 @@ We accept contributions via Pull Requests on [Github](https://github.com/php-amq

## Running Tests

To successfully run the tests you need to first have a stock RabbitMQ broker running locally. Then, run tests like this:

``` bash
$ vendor/bin/phpunit
```
or
``` bash
$ make test
```

### Start RabbitMQ

To successfully run the tests you need to first have a stock RabbitMQ broker running locally

* Using `docker compose`
```
make docker-test-env
```
Note: if you wish to ensure the latest docker images, run this command:
```
make DOCKER_FRESH=true clean docker-test-env
```
* Using the GitHub Actions setup script
Note: this has been tested on Ubuntu 22 and Arch Linux
```
./.ci/ubuntu/gha-setup.sh
```

### Run Tests

* Using an environment started via `make docker-test-env`:
```
make docker-test
```
* Using a local RabbitMQ started by `gha-setup.sh`:
``` bash
make test
```

### Cleanup / Troubleshooting

If you started your environment using `make docker-test-env`, use `docker compose stop` to stop it.

If you ran tests locally, but then decided to use the docker environment to run tests, you should first run `make clean`

**Happy coding**!
35 changes: 34 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
DOCKER_FRESH ?= false

TOXIPROXY_HOST ?= localhost
TOXIPROXY_AMQP_TARGET ?= php-amqplib-rabbitmq
TOXIPROXY_AMQP_PORT ?= 5673

.PHONY: test
test:
./vendor/bin/phpunit
TOXIPROXY_HOST=$(TOXIPROXY_HOST) \
TOXIPROXY_AMQP_TARGET=$(TOXIPROXY_AMQP_TARGET) \
TOXIPROXY_AMQP_PORT=$(TOXIPROXY_AMQP_PORT) \
$(CURDIR)/vendor/bin/phpunit

.PHONY: docs
docs:
wget -qN https://github.com/phpDocumentor/phpDocumentor/releases/download/v3.3.0/phpDocumentor.phar
rm -rf ./docs/*
php -d error_reporting=0 ./phpDocumentor.phar run -v --force --defaultpackagename=PhpAmqpLib --title='php-amqplib' -d ./PhpAmqpLib -t ./docs

.PHONY: benchmark
benchmark:
@echo "Publishing 10k messages with 1KB of content:"
Expand All @@ -16,3 +27,25 @@ benchmark:
php benchmark/stream_tmp_produce.php 1000
@echo "Socket produce 1k:"
php benchmark/socket_tmp_produce.php 1000

.PHONY: docker-test-env
docker-test-env:
ifeq ($(DOCKER_FRESH),true)
docker build --pull --no-cache --tag=php-amqplib-php:latest $(CURDIR)/docker/php
docker compose build --no-cache --pull
docker compose up --pull always --detach
else
docker build --tag=php-amqplib-php:latest $(CURDIR)/docker/php
docker compose up --detach
endif

.PHONY: docker-test
docker-test:
docker run --env-file $(CURDIR)/test.env --network php-amqplib_default \
--volume $(CURDIR):/src --workdir /src \
--user "$$(id -u):$$(id -g)" php-amqplib-php:latest \
/bin/sh -c '/usr/bin/composer install && ./vendor/bin/phpunit'

.PHONY: clean
clean:
git clean -xffd
6 changes: 5 additions & 1 deletion PhpAmqpLib/Wire/IO/StreamIO.php
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,11 @@ public function write($data)
}
$this->throwOnError();
} catch (\ErrorException $e) {
$code = $this->last_error->getCode();
$code = 999;
if ($this->last_error != null)
{
$code = $this->last_error->getCode();
}
$constants = SocketConstants::getInstance();
switch ($code) {
case $constants->SOCKET_EPIPE:
Expand Down
Loading