-
Notifications
You must be signed in to change notification settings - Fork 19
Test writing
Elemental-IRCd uses TCL for its functional testing suite. All new contributions (even ones from the team) are very much encouraged to have a test to ensure that the changes made are functional.
Tests are very concise and declarative, however there are a few peculiarities that TCL has that are worth pointing out.
begin {example test}
set test_channel #exampletest
client me
client you
me >> PRIVMSG $test_channel "Hi there [you nick]!"
you << PRIVMSG $test_channel "Hi there [you nick]!"This creates a test with the description "example test", a test channel (that all related clients will implicitly join) named #exampletest, a couple of clients and then makes sure they can send a message from me to you.
Something that will stand out instantly is the fact that none of the IRC line portions had to be quoted using the standard double quotes ("). This is because TCL commands are somewhat of a hybrid between shell functions and "real" functions like you would see in C or Lua. TCL procedures are actually implemented as a series of arguments being applied against a string denoted by starting with { and ending with }. A side effect of this is that TCL allows bare words as a language primitive, which we heavily take advantage of in tests.
Also in TCL, to make an argument the result of some arbitrary command, you need to wrap it in square brackets ([ and ]). An example:
client oper
puts [oper nick]
# prints the nick of the client referred to by `oper`Creating a client is done using the client proc. When a client is declared it will automatically connect to a random server in the array of servers that are available to connect to. The first argument to client is the name of the object that should be used in TCL to refer to it.
| Flag name | Meaning |
|---|---|
-nick |
Sets client nickname to an arbitrary value (make sure this is unique across all tests) |
-user |
Sets a client username (ident) to an arbitrary value |
-gecos |
Sets a client gecos (real name) to an arbitrary value |
-caps |
Sets the client IRCv3 capabilities |
client god -nick opermcoperface -user floam -gecos Floamtastic
oper godThe nickname of a client is available by the attribute nick applied to a client instance. An example:
client god
puts [god nick]
# prints the nick of the client referred to by `god`The >> operator sends an arbitrary line to the IRC daemon taken in as bare words.
client me
me >> PRIVMSG #foo {ha! I can say words!}The << operator waits for and blocks a line matching what you specify (with shell-style matching) and will fail if the line hasn't been received in about one and a half seconds. This may seem a bit small but the actual tests run for only a few seconds in total, so it is pretty easy to look at the list of tests as they run and see if one is going to fail. The last argument needs to be specified as a TCL curly-brace quoted string to match an RFC 1459 extended argument.
# Master sends TOPIC to $test_channel to change the state for victim
master >> TOPIC $test_channel {This is a test topic}
# Victim blocks on the topic being the exact same as the one master sent
victim << TOPIC $test_channel {This is a test topic}The : operator when applied to a client sets that client as the current global implicit client. By default the implicit client is only changed when:
- A new client is created
- A line is written to a client using the
>>operator - The
:operator is applied to a client
This is useful for emulating block styles in Python or the like:
# set up m_omode.so
oper :
# oper up as god for module loading
oper god
# load m_omode.so
>> MODLOAD extensions/m_omode.sooper takes the first argument as the oper name to run /OPER against. The two values are as follows:
| Name | Purpose |
|---|---|
god |
All privileges |
oper |
Limited privileges, only oper:chghost
|
client god
oper god
client lowpower
oper operMost of the numerics are defined as constants in the tests/lib/numerics.tcl file. In most cases the numeric values should Just Work.
victim :
<< TOPIC $test_channel {This is a test topic}
>> TOPIC $test_channel {No I think this should be the topic}
<< ERR_CHANOPRIVSNEEDEDContributions to this wiki are welcome.