Skip to content

Commit

Permalink
move functions from Assertions to Asserter.
Browse files Browse the repository at this point in the history
  • Loading branch information
Whiteknight committed Apr 27, 2011
1 parent fd119ce commit f5aa0b1
Show file tree
Hide file tree
Showing 2 changed files with 323 additions and 342 deletions.
334 changes: 323 additions & 11 deletions src/test/Asserter.winxed
Expand Up @@ -3,20 +3,332 @@ namespace Rosella { namespace Test
/* Test Asserter to provide an OO-like interface to the functions defined
in the Assert namespace
*/
// TODO: Delete Assert namespace and turn all functions there into methods
// on this object.
// TODO: Add the ability for the user to provide a custom subclass for
// asserter instead.
class Asserter
{
function find_method[vtable](string name)
// Routine to get a default message, if none is provided
function default_message(string msg, int has_msg, string def)
{
var assert_name = name;
return function(var obj, var p [slurpy], var n [slurpy,named]) {
var assert_ns = null;
var assert_name_pmc = "Assert";
${ get_hll_namespace assert_ns, assert_name_pmc };
var assertion = assert_ns.find_sub(assert_name);
assertion(p:[flat], n:[flat]);
};
if (has_msg)
return msg;
return def;
}

// Unconditional fail. Throws a Rosella.Test.Failure
function fail(string why,
int is_internal [optional,named], int has_is_i [opt_flag],
var exception [optional,named], int has_ex [opt_flag]
)
{
using Rosella.build;

if (!has_is_i)
is_internal = 0;
if (!has_ex)
exception = null;

var ex = build(class Rosella.Test.Failure, why, exception, is_internal);
ex.throw();
}

/* Assertion Functions
Each of these functions asserts some condition. If the condition
holds, nothing happens. If the condition fails, we call fail().
*/

function block(string message, var block)
{
if (!block())
self.fail(message);
}

function block_false(string message, var block)
{
if (block())
self.fail(message);
}

function can(var obj, string method,
string message [optional], int has_msg [opt_flag])
{
message = self.default_message(message, has_msg, "item failed 'can'");
int i_can = 0;
${ can i_can, obj, method };
if (!i_can)
self.fail(message);
}

function can_not(var obj, string method,
string message [optional], int has_msg [opt_flag])
{
message = self.default_message(message, has_msg, "item failed 'can_not'");
int i_can = 0;
${ can i_can, obj, method };
if (i_can)
self.fail(message);
}

function defined(var obj,
string message [optional], int has_msg [opt_flag])
{
message = self.default_message(message, has_msg, "item not defined");
int is_defined = 0;
${ defined is_defined, obj };
if (!is_defined)
self.fail(message);
}

function not_defined(var obj,
string message [optional], int has_msg [opt_flag])
{
message = self.default_message(message, has_msg, "item is defined");
int is_defined = 0;
${ defined is_defined, obj };
if (is_defined)
self.fail(message);
}

function does(var obj, var role,
string message [optional], int has_msg [opt_flag])
{
message = self.default_message(message, has_msg, "item failed 'does'");
int obj_does = 0;
${ does obj_does, obj, role };
if (!obj_does)
self.fail(message);
}

function does_not(obj, role, string message [optional], int has_msg [opt_flag])
{
message = self.default_message(message, has_msg, "item failed 'does'");
int obj_does = 0;
${ does obj_does, obj, role };
if (obj_does)
self.fail(message);
}

function equal(var o1, var o2,
string message [optional], int has_msg [opt_flag])
{
message = self.default_message(message, has_msg, "objects not equal");
int equal = 0;
${ iseq equal, o1, o2 };
if (!equal)
self.fail(message);
}

function not_equal(var o1, var o2,
string message [optional], int has_msg [opt_flag])
{
message = self.default_message(message, has_msg, "objects equal");
int equal = 0;
${ iseq equal, o1, o2 };
if (equal)
self.fail(message);
}

function instance_of(var obj, var type, string message [optional], int has_msg [opt_flag])
{
message = self.default_message(message, has_msg, "object is not instance_of");
using Rosella.get_type_class;
var class_obj = get_type_class(type);
int it_isa = 0;
${ isa it_isa, obj, class_obj };
if (!it_isa)
self.fail(message);
}

function not_instance_of(var obj, var type, string message [optional], int has_msg [opt_flag])
{
message = self.default_message(message, has_msg, "object is instance_of");
using Rosella.get_type_class;
var class_obj = get_type_class(type);
int it_isa = 0;
${ isa it_isa, obj, class_obj };
if (it_isa)
self.fail(message);
}

//function isa($obj, $class, string message [optional], int has_msg [opt_flag] = "object not isa") {
// self.fail($message) unless pir::isa__iPP($obj, P6metaclass.get_parrotclass($class));
//}

//function not_isa($obj, $class, string message [optional], int has_msg [opt_flag] = "object isa") {
// self.fail($message) if pir::isa__iPP($obj, P6metaclass.get_parrotclass($class));
//}

// TODO: Port matcher library
//function match($obj, $matcher, string message [optional], int has_msg [opt_flag] = "match failed") {
// unless $matcher.matches($obj) {
// my $explain = $matcher.describe_self("\nExpected ")
// ~ $matcher.describe_failure("\nbut ", $obj);
// self.fail($message ~ $explain);
// }
//}

//function not_match($obj, $matcher, string message [optional], int has_msg [opt_flag]) {
// if $matcher.matches($obj) {
// self.fail($message);
// }
//}

function is_null(var obj, string message [optional], int has_msg [opt_flag])
{
message = self.default_message(message, has_msg, "object is not null");
if (obj != null)
self.fail(message);
}

function not_null(var obj, string message [optional], int has_msg [opt_flag])
{
message = self.default_message(message, has_msg, "object is null");
if (obj == null)
self.fail(message);
}

function same(var o1, var o2, string message [optional], int has_msg [opt_flag])
{
message = self.default_message(message, has_msg, "objects not same");
if (o1 !== o2)
self.fail(message);
}

function not_same(var o1, var o2, string message [optional], int has_msg [opt_flag])
{
message = self.default_message(message, has_msg, "objects are same");
if (o1 === o2)
self.fail(message);
}

function throws(var block, string message [optional], int has_msg [opt_flag])
{
message = self.default_message(message, has_msg, "does not throw");
try {
block();
self.fail(message);
} catch() {}
}

function throws_nothing(var block, string message [optional], int has_msg [opt_flag])
{
message = self.default_message(message, has_msg, "block throws");
try {
block();
} catch(e) {
self.fail(message, e:[named("exception")]);
}
}

function is_true(int bool, string message [optional], int has_msg [opt_flag])
{
message = self.default_message(message, has_msg, "is not true");
if (!bool)
self.fail(message);
}

function is_false(int bool, string message [optional], int has_msg [opt_flag])
{
message = self.default_message(message, has_msg, "is not false");
if (bool)
self.fail(message);
}

//function within_delta($o1, $o2, $delta, string message [optional], int has_msg [opt_flag] "difference not within delta") {
// my $difference = $o1 - $o2;
// $difference = - $difference if $difference < 0;
// self.fail($message) unless $difference < $delta;
//}

//#~ like(obj, regex, message)
//#~ not_like

//#function want_fail($message, &block) {
//# throws(Exception::RosellaFailure, $message, &block);
//#}

//#function want_pass($message, &block) {
//# throws_nothing($message, &block);
//#}

// meta-test. Runs the block as a test, and expects a failure
function expect_fail(var block, string message [optional], int has_msg [opt_flag])
{
message = self.default_message(message, has_msg, "test did not fail");
var exception = null;
try {
block();
} catch (e) {
exception = e;
}
if (exception == null)
self.fail(message);

var payload = exception.payload;
if (payload == null)
self.fail(message, exception:[named("exception")]);

using Rosella.isa_type;
int isa_failure = isa_type(class Rosella.Test.Failure, payload);
if (!isa_failure)
self.fail(message, exception:[named("exception")]);
}

// meta-test. Runs the block as a test, and expects a pass
function expect_pass(var block, string message [optional], int has_msg [opt_flag])
{
message = self.default_message(message, has_msg, "test did not pass");
var exception = null;
try {
block();
} catch (e) {
exception = e;
}
if (exception != null)
self.fail(message, exception:[named("exception")]);
}

// Run the test, show that the output (and maybe the error output) matches
// the values expected
function output_is(var block, string output,
string message [optional], int has_msg [opt_flag],
string erroutput [named,optional], int has_erroutput [opt_flag])
{
using Rosella.IO.swap_handles;
message = self.default_message(message, has_msg, "output did not match");
var stdout = new "StringHandle";
stdout.open("Rosella.Test.Assert.stdout", "rw");
var stderr = new "StringHandle";
stderr.open("Rosella.Test.Assert.stderr", "rw");
var save_handles = swap_handles({"stdout": stdout, "stderr": stderr});
var exception = null;
try {
block();
} catch (e) {
exception = e;
}
swap_handles(save_handles);

if (exception != null) {
say(exception);
self.fail("Block threw exception before output received",
exception:[named("exception")]
);
}

// TODO: We should trim leading/trailing whitespace

string out_str = stdout.readall();
if (out_str != output)
self.fail(sprintf("%s\nExpected: '%s'\nReceived:'%s'", [message, output, out_str]));

if (!has_erroutput)
return;

string errout_str = stderr.readall();
if (errout_str != erroutput)
self.fail(message);
}

}
}}

0 comments on commit f5aa0b1

Please sign in to comment.