mirror of
https://github.com/SaraSmiseth/prosody.git
synced 2025-01-18 13:10:37 +00:00
Create tests (#15)
Created a tests folder which contains pytest and bats tests. Pytest is used to login and send messages to other accounts. Bats is used to check the log for debug messages. This fixes #13.
This commit is contained in:
parent
fc45a7bab1
commit
b70fcbd98e
12 changed files with 353 additions and 1 deletions
26
.github/workflows/test.yml
vendored
Normal file
26
.github/workflows/test.yml
vendored
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
name: Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: dev
|
||||||
|
push:
|
||||||
|
branches: dev
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Checkout submodules
|
||||||
|
uses: textbook/git-checkout-submodule-action@master
|
||||||
|
|
||||||
|
- name: install python3-venv
|
||||||
|
run: sudo apt-get install python3-venv
|
||||||
|
|
||||||
|
- name: build test image
|
||||||
|
run: docker build . -t prosody
|
||||||
|
|
||||||
|
- name: run tests
|
||||||
|
run: cd ./tests/ && ./test.bash
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1 +1,4 @@
|
||||||
data/*
|
data/*
|
||||||
|
tests/certs/
|
||||||
|
tests/venv/
|
||||||
|
tests/__pycache__/
|
||||||
|
|
9
.gitmodules
vendored
Normal file
9
.gitmodules
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[submodule "tests/bats/bats-support"]
|
||||||
|
path = tests/bats/bats-support
|
||||||
|
url = https://github.com/bats-core/bats-support.git
|
||||||
|
[submodule "tests/bats/bats-core"]
|
||||||
|
path = tests/bats/bats-core
|
||||||
|
url = https://github.com/bats-core/bats-core.git
|
||||||
|
[submodule "tests/bats/bats-assert"]
|
||||||
|
path = tests/bats/bats-assert
|
||||||
|
url = https://github.com/bats-core/bats-assert.git
|
1
tests/bats/bats-assert
Submodule
1
tests/bats/bats-assert
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 0a8dd57e2cc6d4cc064b1ed6b4e79b9f7fee096f
|
1
tests/bats/bats-core
Submodule
1
tests/bats/bats-core
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 8fb853a6cbc0169958707381985f3cd59789ccb1
|
1
tests/bats/bats-support
Submodule
1
tests/bats/bats-support
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit d140a65044b2d6810381935ae7f0c94c7023c8c3
|
24
tests/docker-compose.yml
Normal file
24
tests/docker-compose.yml
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
version: '3.7'
|
||||||
|
|
||||||
|
services:
|
||||||
|
prosody:
|
||||||
|
image: prosody
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "5000:5000"
|
||||||
|
- "5222:5222"
|
||||||
|
- "5223:5223"
|
||||||
|
- "5269:5269"
|
||||||
|
- "5281:5281"
|
||||||
|
environment:
|
||||||
|
DOMAIN: localhost
|
||||||
|
E2E_POLICY_WHITELIST: "admin@localhost, user1@localhost"
|
||||||
|
LOG_LEVEL: debug
|
||||||
|
PROSODY_ADMINS: "admin@localhost, admin2@localhost"
|
||||||
|
extra_hosts:
|
||||||
|
- "conference.localhost:127.0.0.1"
|
||||||
|
- "pubsub.localhost:127.0.0.1"
|
||||||
|
- "proxy.localhost:127.0.0.1"
|
||||||
|
- "upload.localhost:127.0.0.1"
|
||||||
|
volumes:
|
||||||
|
- ./certs:/usr/local/etc/prosody/certs
|
25
tests/readme.md
Normal file
25
tests/readme.md
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
# Tests
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
* docker
|
||||||
|
* docker-compose
|
||||||
|
* python 3
|
||||||
|
|
||||||
|
## Run tests
|
||||||
|
|
||||||
|
Execute [`test.bash`](test.bash).
|
||||||
|
|
||||||
|
## Upgrade python packages
|
||||||
|
|
||||||
|
The following will install the newest version of packages in requirements.txt.
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
cat requirements.txt | sed 's/==.*//g' | xargs pip install -U
|
||||||
|
```
|
||||||
|
|
||||||
|
If updates are available --> update and create new version with:
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
pip-chill > requirements.txt
|
||||||
|
```
|
3
tests/requirements.txt
Normal file
3
tests/requirements.txt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
aioxmpp==0.11.0
|
||||||
|
pip-chill==1.0.0
|
||||||
|
pytest-asyncio==0.14.0
|
45
tests/test.bash
Executable file
45
tests/test.bash
Executable file
|
@ -0,0 +1,45 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# generate certs for testing
|
||||||
|
|
||||||
|
generateCert() {
|
||||||
|
DOMAIN="$1"
|
||||||
|
if [[ ! -d certs/"$DOMAIN" ]] ; then
|
||||||
|
mkdir -p certs/"$DOMAIN"
|
||||||
|
cd certs/"$DOMAIN"
|
||||||
|
openssl req -x509 -newkey rsa:4096 -keyout privkey.pem -out fullchain.pem -days 365 -subj "/CN=$DOMAIN" -nodes
|
||||||
|
chmod 777 *.pem
|
||||||
|
cd ../../
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
generateCert "localhost"
|
||||||
|
generateCert "conference.localhost"
|
||||||
|
generateCert "proxy.localhost"
|
||||||
|
generateCert "pubsub.localhost"
|
||||||
|
generateCert "upload.localhost"
|
||||||
|
|
||||||
|
sudo docker-compose down \
|
||||||
|
&& sudo docker-compose up -d \
|
||||||
|
\
|
||||||
|
&& sudo docker exec tests_prosody_1 /bin/bash -c "/entrypoint.sh register admin localhost 12345678" \
|
||||||
|
&& sudo docker exec tests_prosody_1 /bin/bash -c "/entrypoint.sh register user1 localhost 12345678" \
|
||||||
|
&& sudo docker exec tests_prosody_1 /bin/bash -c "/entrypoint.sh register user2 localhost 12345678" \
|
||||||
|
&& sudo docker exec tests_prosody_1 /bin/bash -c "/entrypoint.sh register user3 localhost 12345678" \
|
||||||
|
\
|
||||||
|
&& python --version \
|
||||||
|
&& python3 --version \
|
||||||
|
&& python3 -m venv venv \
|
||||||
|
&& source venv/bin/activate \
|
||||||
|
&& python --version \
|
||||||
|
&& pip --version \
|
||||||
|
&& pip install -r requirements.txt \
|
||||||
|
&& pytest \
|
||||||
|
&& deactivate \
|
||||||
|
&& sleep 5 \
|
||||||
|
&& sudo docker-compose logs \
|
||||||
|
&& ./bats/bats-core/bin/bats tests.bats
|
||||||
|
|
||||||
|
sudo docker-compose down
|
119
tests/test_prosody.py
Normal file
119
tests/test_prosody.py
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
import aiosasl
|
||||||
|
import aioxmpp
|
||||||
|
import aioxmpp.dispatcher
|
||||||
|
import asyncio
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def client(client_username, password):
|
||||||
|
|
||||||
|
jid = aioxmpp.JID.fromstr(client_username)
|
||||||
|
|
||||||
|
client = aioxmpp.PresenceManagedClient(
|
||||||
|
jid,
|
||||||
|
aioxmpp.make_security_layer(
|
||||||
|
password,
|
||||||
|
no_verify=True
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return client
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def client_with_message_dispatcher(client):
|
||||||
|
def message_received(msg):
|
||||||
|
print(msg)
|
||||||
|
print(msg.body)
|
||||||
|
assert msg.body == "Hello World!"
|
||||||
|
|
||||||
|
# obtain an instance of the service
|
||||||
|
message_dispatcher = client.summon(
|
||||||
|
aioxmpp.dispatcher.SimpleMessageDispatcher
|
||||||
|
)
|
||||||
|
|
||||||
|
# register a message callback here
|
||||||
|
message_dispatcher.register_callback(
|
||||||
|
aioxmpp.MessageType.CHAT,
|
||||||
|
None,
|
||||||
|
message_received,
|
||||||
|
)
|
||||||
|
return client
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
@pytest.mark.parametrize("client_username, password", [("admin@localhost", "12345678")])
|
||||||
|
async def test_send_message_from_admin_to_user1(client):
|
||||||
|
recipient_jid = aioxmpp.JID.fromstr("user1@localhost")
|
||||||
|
async with client.connected() as stream:
|
||||||
|
msg = aioxmpp.Message(
|
||||||
|
to=recipient_jid,
|
||||||
|
type_=aioxmpp.MessageType.CHAT,
|
||||||
|
)
|
||||||
|
# None is for "default language"
|
||||||
|
msg.body[None] = "Hello World!"
|
||||||
|
|
||||||
|
await client.send(msg)
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
@pytest.mark.parametrize("client_username, password", [("admin@localhost", "12345678")])
|
||||||
|
async def test_send_message_from_admin_to_user2(client):
|
||||||
|
recipient_jid = aioxmpp.JID.fromstr("user2@localhost")
|
||||||
|
async with client.connected() as stream:
|
||||||
|
msg = aioxmpp.Message(
|
||||||
|
to=recipient_jid,
|
||||||
|
type_=aioxmpp.MessageType.CHAT,
|
||||||
|
)
|
||||||
|
msg.body[None] = "Hello World!"
|
||||||
|
|
||||||
|
await client.send(msg)
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
@pytest.mark.parametrize("client_username, password", [("user1@localhost", "12345678")])
|
||||||
|
async def test_send_message_from_user1_to_user2(client):
|
||||||
|
recipient_jid = aioxmpp.JID.fromstr("user2@localhost")
|
||||||
|
async with client.connected() as stream:
|
||||||
|
msg = aioxmpp.Message(
|
||||||
|
to=recipient_jid,
|
||||||
|
type_=aioxmpp.MessageType.CHAT,
|
||||||
|
)
|
||||||
|
msg.body[None] = "Hello World!"
|
||||||
|
|
||||||
|
await client.send(msg)
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
@pytest.mark.parametrize("client_username, password", [("user2@localhost", "12345678")])
|
||||||
|
async def test_send_message_from_user2_to_user3(client):
|
||||||
|
recipient_jid = aioxmpp.JID.fromstr("user3@localhost")
|
||||||
|
async with client.connected() as stream:
|
||||||
|
msg = aioxmpp.Message(
|
||||||
|
to=recipient_jid,
|
||||||
|
type_=aioxmpp.MessageType.CHAT,
|
||||||
|
)
|
||||||
|
msg.body[None] = "Hello World!"
|
||||||
|
|
||||||
|
await client.send(msg)
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
@pytest.mark.parametrize("client_username, password", [("user2@localhost", "12345678")])
|
||||||
|
async def test_send_message_from_user2_to_nonexisting(client):
|
||||||
|
recipient_jid = aioxmpp.JID.fromstr("nonexisting@localhost")
|
||||||
|
async with client.connected() as stream:
|
||||||
|
msg = aioxmpp.Message(
|
||||||
|
to=recipient_jid,
|
||||||
|
type_=aioxmpp.MessageType.CHAT,
|
||||||
|
)
|
||||||
|
msg.body[None] = "Hello World!"
|
||||||
|
|
||||||
|
await client.send(msg)
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
@pytest.mark.parametrize("client_username, password", [("user2@localhost", "wrong password")])
|
||||||
|
async def test_can_not_log_in_with_wrong_password(client):
|
||||||
|
with pytest.raises(aiosasl.AuthenticationFailure):
|
||||||
|
recipient_jid = aioxmpp.JID.fromstr("nonexisting@localhost")
|
||||||
|
async with client.connected() as stream:
|
||||||
|
msg = aioxmpp.Message(
|
||||||
|
to=recipient_jid,
|
||||||
|
type_=aioxmpp.MessageType.CHAT,
|
||||||
|
)
|
||||||
|
msg.body[None] = "Hello World!"
|
||||||
|
|
||||||
|
await client.send(msg)
|
95
tests/tests.bats
Normal file
95
tests/tests.bats
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
# For tests with pipes see: https://github.com/sstephenson/bats/issues/10
|
||||||
|
|
||||||
|
load 'bats/bats-support/load'
|
||||||
|
load 'bats/bats-assert/load'
|
||||||
|
|
||||||
|
# group alternation in regex because the xml properties switch around. sometimes 'type=...' comes after 'to=...' and sometimes before
|
||||||
|
@test "Should send 5 messages" {
|
||||||
|
run bash -c "sudo docker-compose logs | grep -E \"Received\[c2s\]: <message (type='chat'|to='.*@localhost'|id=':.*') (type='chat'|to='.*@localhost'|id=':.*') (type='chat'|to='.*@localhost'|id=':.*')>\" | wc -l"
|
||||||
|
assert_success
|
||||||
|
assert_output "5"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Should select certificate for localhost" {
|
||||||
|
run bash -c "sudo docker-compose logs | grep \"Selecting certificate /usr/local/etc/prosody/certs/localhost/fullchain.pem with key /usr/local/etc/prosody/certs/localhost/privkey.pem for localhost\" | wc -l"
|
||||||
|
assert_success
|
||||||
|
assert_output "3"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Should select certificate for conference.localhost" {
|
||||||
|
run bash -c "sudo docker-compose logs | grep \"Selecting certificate /usr/local/etc/prosody/certs/conference.localhost/fullchain.pem with key /usr/local/etc/prosody/certs/conference.localhost/privkey.pem for conference.localhost\" | wc -l"
|
||||||
|
assert_success
|
||||||
|
assert_output "3"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Should select certificate for proxy.localhost" {
|
||||||
|
run bash -c "sudo docker-compose logs | grep \"Selecting certificate /usr/local/etc/prosody/certs/proxy.localhost/fullchain.pem with key /usr/local/etc/prosody/certs/proxy.localhost/privkey.pem for proxy.localhost\" | wc -l"
|
||||||
|
assert_success
|
||||||
|
assert_output "3"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Should select certificate for pubsub.localhost" {
|
||||||
|
run bash -c "sudo docker-compose logs | grep \"Selecting certificate /usr/local/etc/prosody/certs/pubsub.localhost/fullchain.pem with key /usr/local/etc/prosody/certs/pubsub.localhost/privkey.pem for pubsub.localhost\" | wc -l"
|
||||||
|
assert_success
|
||||||
|
assert_output "3"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Should select certificate for upload.localhost" {
|
||||||
|
run bash -c "sudo docker-compose logs | grep \"Selecting certificate /usr/local/etc/prosody/certs/upload.localhost/fullchain.pem with key /usr/local/etc/prosody/certs/upload.localhost/privkey.pem for upload.localhost\" | wc -l"
|
||||||
|
assert_success
|
||||||
|
assert_output "3"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Should log error for user with wrong password" {
|
||||||
|
run bash -c "sudo docker-compose logs | grep \"Session closed by remote with error: undefined-condition (user intervention: authentication failed: authentication aborted by user)\""
|
||||||
|
assert_success
|
||||||
|
assert_output
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Should activate s2s" {
|
||||||
|
run bash -c "sudo docker-compose logs | grep -E \"Activated service 's2s' on (\[::\]:5269|\[\*\]:5269), (\[::\]:5269|\[\*\]:5269)\""
|
||||||
|
assert_success
|
||||||
|
assert_output
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Should activate c2s" {
|
||||||
|
run bash -c "sudo docker-compose logs | grep -E \"Activated service 'c2s' on (\[::\]:5222|\[\*\]:5222), (\[::\]:5222|\[\*\]:5222)\""
|
||||||
|
assert_success
|
||||||
|
assert_output
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Should activate legacy_ssl" {
|
||||||
|
run bash -c "sudo docker-compose logs | grep -E \"Activated service 'legacy_ssl' on (\[::\]:5223|\[\*\]:5223), (\[::\]:5223|\[\*\]:5223)\""
|
||||||
|
assert_success
|
||||||
|
assert_output
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Should activate proxy65" {
|
||||||
|
run bash -c "sudo docker-compose logs | grep -E \"Activated service 'proxy65' on (\[::\]:5000|\[\*\]:5000), (\[::\]:5000|\[\*\]:5000)\""
|
||||||
|
assert_success
|
||||||
|
assert_output
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Should activate http" {
|
||||||
|
run bash -c "sudo docker-compose logs | grep -E \"Activated service 'http' on (\[::\]:5280|\[\*\]:5280), (\[::\]:5280|\[\*\]:5280)\""
|
||||||
|
assert_success
|
||||||
|
assert_output
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Should activate https" {
|
||||||
|
run bash -c "sudo docker-compose logs | grep -E \"Activated service 'https' on (\[::\]:5281|\[\*\]:5281), (\[::\]:5281|\[\*\]:5281)\""
|
||||||
|
assert_success
|
||||||
|
assert_output
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Should load module cloud_notify" {
|
||||||
|
run bash -c "sudo docker-compose logs | grep \"localhost:cloud_notify.*info.*Module loaded\""
|
||||||
|
assert_success
|
||||||
|
assert_output
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Should show upload URL" {
|
||||||
|
run bash -c "sudo docker-compose logs | grep \"URL: <https:\/\/upload.localhost:5281\/upload> - Ensure this can be reached by users\""
|
||||||
|
assert_success
|
||||||
|
assert_output
|
||||||
|
}
|
Loading…
Reference in a new issue