Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP Protocol testrunner #264

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
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
93 changes: 93 additions & 0 deletions src/kvparse.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// Parse 'key=val key="val" key="val val2" "key name"=val' into an object
module.exports = function kvParse(inp) {
let data = {};
let pos = 0;
let escapeChar = '\\';

while (pos < inp.length) {
let key = '';
let val = '';

key = readToken();
ffwd();
if (inp[pos] === '=') {
skip();
val = readToken({isValue: true});
} else {
ffwd();
val = true;
}

data[key] = val;
}

return data;

// Fast forward past whitespace
function ffwd() {
while (inp[pos] === ' ' && pos < inp.length) {
pos++;
}
}

// Skip the current position
function skip() {
pos++;
}

// Read a block of characters. Quoted allows spaces
function readToken(opts={isValue:false}) {
let inQuote = false;
let buffer = '';

ffwd();
do {
let cur = inp[pos];
if (!cur) {
break;
}

// Opening quote
if (!inQuote && isQuote(cur)) {
inQuote = true;
continue;
}

// Escaped closing quote = not a closing quote
if (inQuote && isQuote(cur) && isEscaped()) {
buffer += cur;
continue;
}

// Closing quote
if (inQuote && isQuote(cur)) {
inQuote = false;
skip();
break;
}

if (!opts.isValue) {
if (!inQuote && (cur === ' ' || cur === '=')) {
break;
}
} else {
// Values allow = characters
if (!inQuote && cur === ' ') {
break;
}
}

buffer += cur;
} while(++pos < inp.length)

return buffer;
}

function isQuote(char) {
return char === '"';
}

function isEscaped() {
return inp[pos-1] === escapeChar;
}
}
9 changes: 9 additions & 0 deletions test/protocol.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
'use strict';
/* globals describe, it */
const TestProtocol = require('../test_protocol/');

describe('protocol test runners', async function() {
it('should run all protocol test scripts', async function() {
await TestProtocol()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we not want to hook it into the tests a little bit better, so each test becomes it and gets reported correctly by the test software?

});
});
88 changes: 88 additions & 0 deletions test_protocol/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
const fs = require('fs');
const TestRunner = require('./testrunner');
const TestRunnerTransport = require('./testrunnertransport');
const IRC = require('../src/');

module.exports = runScripts;

isMain = require.main === module;

(async function() {
if (isMain) {
await runScripts();
}
})();

async function runScripts() {
// Run through each test runner script and run it
let scriptsDir = __dirname + '/test_scripts/';
let scripts = fs.readdirSync(scriptsDir);
for(let i=0; i<scripts.length; i++) {
let scriptContent = fs.readFileSync(scriptsDir + scripts[i], 'utf8');
await runScript(scriptContent);
}
};

async function runScript(script) {
let bot = null;

const r = new TestRunner();
r.load(script);
r.onReset = () => {
createNewIrcClient();
};

// Start running the test runner before creating the client to be sure all events are caught
let scriptRun = r.run();
createNewIrcClient();
await scriptRun;
if (bot) {
bot.connection.end();
}

function createNewIrcClient() {
if (bot) {
bot.connection.end();
}

bot = new IRC.Client();
bot.use(CatchAllMiddleware(r));
bot.connect({
transport: createTestRunnerTransport(r),
host: 'irc.example.net',
nick: 'ircfrw_testrunner',
});
bot.on('registered', function() {
bot.join('#prawnsalad');
});
bot.on('join', event => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these events temporary? Should be in the txt files.

if (event.nick === bot.user.nick) {
bot.who(event.channel);
}
});

if (isMain) {
//bot.on('debug', l => console.log('[debug]', l));
bot.on('raw', event => console.log(`[raw ${event.from_server?'s':'c'}]`, event.line));
}
}
};

// Create an irc-framework transport
function createTestRunnerTransport(r) {
return function(...args) {
return new TestRunnerTransport(r, ...args)
};
}

// Pass all framework events to TestRunner r
function CatchAllMiddleware(r) {
return function(client, raw_events, parsed_events) {
parsed_events.use(theMiddleware);
};

function theMiddleware(command, event, client, next) {
r.addEventFromClient(command, event)
next();
}
}
10 changes: 10 additions & 0 deletions test_protocol/test_scripts/register_using_readwait.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Testing IRC registration without CAP support

# wait until we get the USER command
READWAIT USER $ $ $ $

# register the client with the nick "testbot"
SEND :src 001 testbot something :Welcome home

# the client should now trigger a "registered" event
EVENT registered nick=testbot
6 changes: 6 additions & 0 deletions test_protocol/test_scripts/register_without_cap.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Testing IRC registration without CAP support
READ CAP LS 302
READ NICK $nick
READ USER $ $ $ $
SEND :src 001 $nick something :Welcome home
EVENT registered nick=$nick
20 changes: 20 additions & 0 deletions test_protocol/test_scripts/script_reset_test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Test script RESET example

READWAIT USER $ $ $ $
SEND :src 001 nick1 something :Welcome home
EVENT registered nick=nick1

RESET
READWAIT USER $ $ $ $
SEND :src 001 nick2 something :Welcome home
EVENT registered nick=nick2

RESET
READWAIT USER $ $ $ $
SEND :src 001 nick3 something :Welcome home
EVENT registered nick=nick3

RESET
READWAIT USER $ $ $ $
SEND :src 001 nick4 something :Welcome home
EVENT registered nick=nick4
11 changes: 11 additions & 0 deletions test_protocol/test_scripts/who_after_join.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Testing sending WHO after joining a channel
READ CAP LS 302
READ NICK $nick
READ USER $ $ $ $
SEND :src 001 $nick something :Welcome home
SEND :src 005 $nick a b c :is supported
READ JOIN $chan
SEND :$nick JOIN $chan
EVENTWAIT join channel="$chan" nick=$nick
READ WHO $1
EXPECT $1="$chan"
Loading