Skip to content

Commit

Permalink
- added a helper for testing parsers
Browse files Browse the repository at this point in the history
  • Loading branch information
renggli committed Jun 20, 2013
1 parent 552bdad commit f3a7cac
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 72 deletions.
92 changes: 92 additions & 0 deletions lib/test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright (c) 2013, Lukas Renggli <renggli@gmail.com>

/**
* This package contains matches to write test for parsers.
*
* Examples:
*
* var json = new JsonParser();
*
* // verifies that the input gets parsed and all input is consumed
* expect('{"a": 1}', accepts(new JsonParser()));
*
* // verifies that the input gets parsed to a dictionary and that all input is consumed
* expect('{"a": 1}', parses(new JsonParser(), {'a': 1}));
*/

library test_util;

import 'package:unittest/matcher.dart';
import 'package:petitparser/petitparser.dart';

/**
* Returns a matcher that succeeds if the [parser] accepts the input.
*/
Matcher accept(Parser parser) {
return new _Accept(parser);
}

class _Accept extends BaseMatcher {
final Parser _parser;
_Accept(this._parser);
bool matches(item, Map matchState) {
return _parser.accept(item);
}
Description describe(Description description) {
return description.add('$_parser to accept input');
}
}

/**
* Returns a matcher that succeeds if the [parser] results in [matcher].
*/
Matcher parse(Parser parser, dynamic matcher, [int position = -1]) {
return new _Parse(parser, wrapMatcher(matcher), position);
}

class _Parse extends BaseMatcher {
final Parser _parser;
final Matcher _matcher;
final int _position;
_Parse(this._parser, this._matcher, this._position);
bool matches(item, Map matchState) {
Result result = _parser.parse(item);
if (!_matcher.matches(result.value, matchState)) {
addStateInfo(matchState, {'property': 'value', 'result': result});
return false;
}
if (_position >= 0 && !equals(_position).matches(result.position, matchState)) {
addStateInfo(matchState, {'property': 'position', 'result': result});
return false;
}
return true;
}
Description describe(Description description) {
return description.add('$_parser to accept ').addDescriptionOf(_matcher);
}
Description describeMismatch(item, Description mismatchDescription,
Map matchState, bool verbose) {
mismatchDescription.add('has parse result ').add('"${matchState['result']}"');
if (matchState['property'] == 'value') {
mismatchDescription.add(' which parse result ');
var subDescription = new StringDescription();
_matcher.describeMismatch(matchState['result'].value, subDescription,
matchState['state'], verbose);
if (subDescription.length > 0) {
mismatchDescription.add(subDescription);
} else {
mismatchDescription.add('doesn\'t match');
_matcher.describe(mismatchDescription);
}
return mismatchDescription;
} else if (matchState['property'] == 'position') {
mismatchDescription
.add(' that consumes input to ')
.add(matchState['result'].position.toString())
.add(' instead of ')
.add(_position.toString());
return mismatchDescription;
}
throw new Exception('Internal matcher error');
}
}
2 changes: 2 additions & 0 deletions test/all_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ import 'core_test.dart' as core_test;
import 'json_test.dart' as json_test;
import 'lisp_test.dart' as lisp_test;
import 'smalltalk_test.dart' as smalltalk_test;
import 'test_test.dart' as test_test;
import 'xml_test.dart' as xml_test;

void main() {
group('PetitParser', core_test.main);
group('JSON', json_test.main);
group('LISP', lisp_test.main);
group('Smalltalk', smalltalk_test.main);
group('Test', test_test.main);
group('XML', xml_test.main);
}
22 changes: 22 additions & 0 deletions test/test_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) 2013, Lukas Renggli <renggli@gmail.com>

library test_test;

import 'package:petitparser/petitparser.dart';
import 'package:petitparser/test.dart';
import 'package:unittest/unittest.dart';

void main() {
test('accept', () {
expect('a', accept(char('a')));
expect('b', isNot(accept(char('a'))));
});
test('parse', () {
expect('a', parse(char('a'), 'a'));
expect('a', isNot(parse(char('a'), 'b')));
});
test('parse (with position)', () {
expect('a', parse(char('a'), 'a', 1));
expect('a', isNot(parse(char('a'), 'a', 0)));
});
}
72 changes: 0 additions & 72 deletions test/test_util.dart

This file was deleted.

0 comments on commit f3a7cac

Please sign in to comment.