• Stars
    star
    127
  • Rank 282,790 (Top 6 %)
  • Language
    Erlang
  • License
    Apache License 2.0
  • Created over 13 years ago
  • Updated 11 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

An XMPP client library in Erlang for conveniently testing XMPP servers

Escalus

Escalus is an Erlang XMPP client library. It began as a tool for convenient testing of XMPP servers, but can also be used as a standalone Erlang application.

Escalus is aimed at checking correctness of XMPP server behaviour, in contrast to tools such as Tsung which are about stress testing and don't verify correctness.

This tool, escalus, is used by ESL's amoc for load tests against ESL's MongooseIM.

Quick start

The test/example_SUITE.erl file contains a minimalistic example of an Escalus test suite.

You should include escalus.hrl file and the Common Test header:

-include_lib("escalus/include/escalus.hrl").
-include_lib("common_test/include/ct.hrl").

Escalus contains functions escalus:init_per_suite/1, escalus:end_per_suite/1, escalus:init_per_testcase and escalus:end_per_testcase which should be called in appropriate Common Test callback functions. Calling escalus:init_per_testcase is mandatory as this function initializes the runtime support for escalus:story (i.e. escalus_cleaner -- actually, you can do it manually if you know what you're doing).

You can specify users that will take part in your tests in Common Test config files, look at test/test.config file that comes with Escalus:

{escalus_users, [
    {alice, [
        {username, "alice"},
        {server, "localhost"},
        {password, "makota"}]},
    {bob, [
        {username, "bob"},
        {server, "localhost"},
        {password, "bobcat"}]}
]}.

Escalus can create and delete those users in two ways:

  • using in-band registration XEP-0077 when it is supported by the server and has no limits on number of registrations per second (configure registration_timeout to infinity in case of ejabberd).
  • using erlang rpc calls to the ejabberd_admin:register/2 function (in case of MongooseIM or ejabberd as the tested server and the in-band registration is disabled)

You create and delete the users by calling escalus:create_users/1 and escalus:delete_users/1:

init_per_group(_GroupName, Config) ->
    escalus:create_users(Config).

end_per_group(_GroupName, Config) ->
    escalus:delete_users(Config).

In our exemplary test case it is done in init_per_group and end_per_group functions, but you could as well do it in init-/end_per_suite if you prefer. Deleting users should clean all their data (e.g. roster buddies), so it improves test isolation, but takes longer.

In most of the test cases you will use escalus:story/3 function. Story wraps all the test and does the cleanup and initialisation:

messages_story(Config) ->
    escalus:story(Config, [1, 1], fun(Alice, Bob) ->

        %% Alice sends a message to Bob
        escalus:send(Alice, escalus_stanza:chat_to(Bob, <<"OH, HAI!">>)),

        %% Bob gets the message
        escalus:assert(is_chat_message, [<<"OH, HAI!">>],
                       escalus:wait_for_stanza(Bob))

    end).

The story above involves two users (second argument is a two-element list) each having one resource (list contains ones). As you see from the config files, those users are Alice and Bob. Escalus logs in users at the beginning of the story and logs them out after it ends (either successfully or by crash).

It's also possible to designate users taking part in a story more specifically:

messages_story(Config) ->
    escalus:story(Config, [{alice, 1}, {kate, 1}], fun(Alice, Kate) ->
        ...
    end).

That allows one to choose users which are not consecutive in test/test.config.

Inside the story you can use escalus:send/2 function to send stanzas, functions from escalus_stanza module to create them and escalus:wait_for_stanza to receive them.

wait_for_stanza makes test fail if no stanza arrives up to a timeout. There is also wait_for_stanzas function which takes number of stanzas N as an argument and returns N-element or shorter list of stanzas, returning less stanzas instead of crashing. Both wait_for_stanza and wait_for_stanzas can take an extra argument -- timeout in milliseconds. The default timeout value is one second.

You make assertions using escalus:assert/3 function. First argument is the predicate. It can be a fun, a {module, function} tuple or an atom. Atoms refer to functions from escalus_pred module. Second argument is a parameter list and third is a stanza that we assert things about. There is escalus:assert/2 function that is equivalent to assert/3 with empty parameter list. Calling escalus:assert(Pred, [Param1, Param2], Stanza) makes sure that Pred(Param1, Param2, Stanza) yields true. Stanza is separate from parameters to improve error reporting.

Escalus as a standalone application

It's possible to use Escalus as a standalone application, i.e. outside a Common Test test suite (and without any reliance on the common_test application and its modules). If you use rebar3 tool there are only few steps to generate full escalus release. Just type in your bash shell:

rebar3 release

and wait until it finishes. It is now possible to start erlang shell with command:

$ESCALUS_ROOT/_build/default/rel/escalus/bin/escalus

You can now enjoy usage of escalus application in your erlang release! In order to use escalus as standalone application without rebar3 some prerequisites must be met.

Firstly, Escalus must be started just like any other application:

> application:ensure_all_started(escalus).

This makes predefined environment variables from escalus.app available for access by application:get_env. These options and their respective values for running without Common Test are:

{env, [{config_file, "priv/escalus.config"}]}

To recap:

  • config_file must be set to a configuration file location; this location may be absolute or relative (in which case the file will be searched for relative to the project directory).

Note, that in a real security-conscious setting you probably shouldn't store clear text user passwords in this file (though that's exactly what the example does - remember Escalus is still mostly a testing tool).

If you don't want to rely on the application resource file (escalus.app/escalus.app.src) you can set both of these options just after loading Escalus:

> application:ensure_all_started(escalus).
> application:set_env(escalus, config_file, "/absolute/or/relative/path").

Keep in mind that calling application:ensure_all_started(escalus) will overwrite the values with stuff from escalus.app. Set the variables after the application is started.

Config file location

If the config_file value starts with / it's interpreted as an absolute path and left as is. Otherwise, it's interpreted as a relative path to the project directory. The project directory is the directory one level higher than the directory containing ejabberd_ct.beam. In case of a standard Git checkout the project directory is simply escalus.

escalus/
├── .git/
├── ...
├── docs/
├── ebin/
│   ├── ...
│   ├── escalus_ct.beam
│   └── ...
├── src/
└── ...

Example shell session

Fire an Erlang shell:

erl -pa ebin deps/*/ebin

Basic example

Run example:

application:ensure_all_started(escalus).
{ok, Config} = file:consult("priv/escalus.config").
CarolSpec = escalus_users:get_options(Config, carol).
{ok, Carol, _, _} = escalus_connection:start(CarolSpec).
escalus_connection:send(Carol, escalus_stanza:chat_to(alice, "hi")).
escalus_connection:stop(Carol).

Story example

Please note that escalus:story/3 and escalus:create_users/2 are intended to be used in a testing environment, i.e. with Common Test available. Specifically, escalus:create_users/2 will not work without Common Test and with non-XMPP registration method chosen (i.e. RPC based user registration). In case of MongooseIM or ejabberd, please ensure mod_register is enabled (and, depending on your scenario, probably configured not to send a welcome message).

Run example:

X2SFun = fun(X) -> lists:flatten(io_lib:format("~p~n", [X])) end.
{ok, Config0} = file:consult("priv/escalus.config").
application:ensure_all_started(escalus).
escalus:create_users(Config0, {by_name, [alice, mike]}).
Config = escalus_event:start(escalus_cleaner:start(Config0)).
SendFun = fun(A, B) -> escalus:send(A, escalus_stanza:chat_to(B, "hi")), ok end.
RecvFun = fun(B) -> [S] = escalus:wait_for_stanzas(B, 1), {ok, S} end.
StoryFun = fun(A, B) -> SendFun(A, B), {ok, S} = RecvFun(B), erlang:display(X2SFun(S)) end.
escalus:story(Config, [{mike, 1}, {alice,1}], StoryFun).
escalus_cleaner:stop(escalus_event:stop(Config)).
escalus:delete_users(Config, {by_name, [alice, mike]}).

Naming

According to Wikipedia, Prince Escalus, of the House Escalus, is the voice of authority in Verona, and appears only three times within the text and only to administer justice.

It follows the great tradition to use characters of William Shakespeare's Romeo and Juliet in the XMPP specifications.

More Repositories

1

MongooseIM

MongooseIM is Erlang Solutions' robust, scalable and efficient XMPP server, aimed at large installations. Specifically designed for enterprise purposes, it is fault-tolerant and can utilise the resources of multiple clustered machines.
Erlang
1,660
star
2

gradient

Gradient is a static typechecker for Elixir
Elixir
431
star
3

erlang-handbook

A concise reference for Erlang
TeX
296
star
4

erlang_ale

Erlang Actor Library for Embedded -- An embedded framework from Erlang Solutions
C
208
star
5

lhttpc

lhttpc is a lightweight HTTP/1.1 client implemented in Erlang.
Erlang
127
star
6

MongooseICE

STUN/TURN server written in Elixir
Elixir
118
star
7

MongoosePush

MongoosePush is a simple Elixir RESTful service allowing to send push notification via FCM and/or APNS.
Elixir
108
star
8

elarm

Erlang
102
star
9

amoc

A load-testing framework for running massively parallel tests
Erlang
96
star
10

ex_rabbit_pool

RabbitMQ connection pooling in Elixir
Elixir
73
star
11

erlang-web

Erlang
50
star
12

parcv

Computer vision demo running on the parallella board
C
38
star
13

mangosta-android

MongooseIM client for Android
Java
31
star
14

mangosta-ios

MongooseIM client for iOS
Swift
30
star
15

sparrow

iOS and Android push notifications for Elixir.
Elixir
30
star
16

mongooseim-docker

Shell
27
star
17

segmented_cache

Modern, performant, and extensible, Erlang in-memory cache
Erlang
27
star
18

ex_docker_build

docker build with support for bind mounts at build time via Docker Remote API
Elixir
25
star
19

ejabberd_tests

Erlang
23
star
20

flex

A simple Elixir InfluxDB client.
Elixir
20
star
21

erl_fuzzy_match

Erlang Fuzzy String Matcher
Erlang
18
star
22

lager_graylog

Lager is a standard logging tool for Erlang, this project crates lager formatter to output messages in gelf format and lager backend to send messages via UDP.
Erlang
17
star
23

arnold

Time series data forecasting tool made in Elixir using Axon library
Elixir
17
star
24

fast_scram

Fastest SCRAM's implementation for Erlang & OTP, aiming at performance and statelessness for ease-of-use
Erlang
17
star
25

tracerl

Dynamic tracing tests and utilities for Erlang/OTP
Erlang
17
star
26

cets

A library to synchronise records from the ETS tables between nodes
Erlang
15
star
27

jerboa

STUN/TURN encoder, decoder and client library in Elixir
Elixir
14
star
28

MongooseHelm

Helm chart definitions for the Mongoose stack (MongooseIM, MongoosePush)
Erlang
11
star
29

rebar3_codecov

A rebar3 plugin which converts .coverdata files to JSON format, compatible with
Erlang
11
star
30

elibcloud

Erlang wrapper for Libcloud
Erlang
10
star
31

packages

Makefile- and Docker-based build system for ESL's erlang and elixir binary packages.
Python
9
star
32

fast_pbkdf2

Erlang's best pbkdf2 implementation
C
9
star
33

rabbitmq-docker

Dockerfile
8
star
34

usec

Convert anything to microseconds and back.
Erlang
8
star
35

c3card

A workshop at CodeBEAM America 2024 showcasing custom hardware and Erlang-based firmware development using AtomVM.
Erlang
8
star
36

esl-rabbitmq-client

RabbitMQ Client for Erlang, built by ESL
Erlang
7
star
37

amoc-arsenal-xmpp

Erlang
7
star
38

erlang-osx-installer

Erlang Installer & Auto-Updater for macOS
Swift
6
star
39

buildex_api

Elixir
6
star
40

mongoose_jid

Erlang
5
star
41

movim-docker

Dockerfiles for movim application
Shell
5
star
42

jaguar

Elixir
5
star
43

wombat_discovery

Erlang
5
star
44

logger_graylog_backend

Elixir's Logger backend for Graylog
Elixir
5
star
45

opuntia

Opuntia is a basic set of tools for traffic shaping for erlang and elixir. Because if you touch it too fast, it stings you.
Erlang
5
star
46

gradient_macros

Slim Gradient compile-time support
Elixir
4
star
47

chirp_cockroach

Demo project: Chris McCord's Twitter clone with a CockroachDB backend
Elixir
4
star
48

buildex_jobs

Buildex service which receives and processes build instructions
Elixir
4
star
49

throttle

Experimental implementation of a simple throttle
Erlang
4
star
50

wombat-discovery

Plugin for Wombat to automatically add nodes
Elixir
4
star
51

buildex_poller

Buildex service which polls github (others to follow) and triggers builds via RabbitMQ
Elixir
4
star
52

release_poller

Elixir
4
star
53

base16

The last time I hexadecimify Erlang binaries...
Erlang
4
star
54

poc_tensorflow_mushrooms

Elixir
3
star
55

beam_olympics_nerves

Getting Beam Olympics to run on a Raspberry Pi through Nerves. Phoenix leaderboard included.
Erlang
3
star
56

erlang-plts

Pregenerated Dialyzer PLTs for a number of Erlang versions
Python
3
star
57

exometer_report_statsd

Erlang
3
star
58

seta

Work-stealing scheduler
JavaScript
3
star
59

ice_demo

Elixir
3
star
60

loadex

simple small open load generator
Elixir
2
star
61

MongooseDocs

Documentation for MongooseIM, in this repo's gh-pages: https://esl.github.io/MongooseDocs/latest/
HTML
2
star
62

buildex_ui

Buildex service which provides Oauth login and build configuration management
2
star
63

rabbitmq-queue-info

Makefile
2
star
64

gapp

Erlang
2
star
65

ex_github_poller

An elixir application to poll github repositories ... wip
Elixir
2
star
66

helm-chart

Shell
2
star
67

elarm_mailer

SMTP reporting for elarm
Erlang
2
star
68

Mercutio

Erlang
2
star
69

percacdat

Persistent Cached Data structures
Erlang
2
star
70

elixirconf-eu-jekyll

HTML
2
star
71

ice

Erlang
2
star
72

jekyll-codesync-global

jekyll version of codesync-global
SCSS
2
star
73

buildex_common

Modules shared by buildex projects
Elixir
2
star
74

cfg

Erlang
2
star
75

foo-phx-cowboy-2.6

phoenix 1.4 / cowboy-2.6 bootstrap project
Elixir
2
star
76

exometer_report_graphite

Erlang
2
star
77

mongooseim-ct-reports

Autogenerated repository for Common Tests reports. Used by MongooseIM team
JavaScript
2
star
78

bryan_cb_sf_2020_talk

bryan hunt codebeam talk
Makefile
2
star
79

amoc-swarm

Dockerfile
2
star
80

node-with-build-tools

node with build tools pre-installed
Dockerfile
2
star
81

release_tasks

Elixir
2
star
82

graphql-erlang

Erlang
2
star
83

amoc_rest

The generated server code for AMOC REST API
Erlang
2
star
84

elixometer

Elixir
2
star
85

observability

Examples for the Erlang and Elixir Observability tutorial
Erlang
1
star
86

jekyll-codesync-global-2

CSS
1
star
87

erlangusergroup

1
star
88

circleci-mim-results

JavaScript
1
star
89

sappan

Erlang
1
star
90

virtual-elixirconf-eu-jekyll

HTML
1
star
91

tanka-alpine

devops docker image with tanka, jsonnet, and jsonnet-package pre-installed
Dockerfile
1
star
92

ml-hackathon

Python
1
star
93

circleci-kubernetes-deployer

docker image with helm, kubectl, google cloud tools, etc baked in
Dockerfile
1
star
94

code-beam-america

HTML
1
star
95

plantproxy

Elixir
1
star
96

lambdadays-jekyll

convert lambdadays from custom webserver to jekyll
HTML
1
star