Important change to the START_SET and END_SET macros to stop their use

being confusing.  They now both take a simple C-string argument which
names the set, and the macros check that each end matches a start of
the same name.  Since tis means that a START_SET no longer takes an
argument sayng whether or notthe set is to be skipped, we now have a
SKIP macro to be used inside a set to skip to the end of it.  This
is actually more versatile as we can have multiple SKIP macros in the
same set, each providing a different reason for the set being skipped.
Also removed a few obsolete/unused functions and macros.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/tools/make/trunk@32355 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2011-02-24 16:26:01 +00:00
parent 3895ad8c89
commit 21c545b319
12 changed files with 291 additions and 255 deletions

View file

@ -1,3 +1,26 @@
2011-01-24 Richard Frith-Macdonald <rfm@gnu.org>
* TestFramework/example9.m:
* TestFramework/ObjectTesting.h:
* TestFramework/README:
* TestFramework/Testing.h:
* TestFramework/example2.m:
* TestFramework/example3.m:
* TestFramework/example4.m:
* TestFramework/example5.m:
* TestFramework/example6.m:
* TestFramework/example7.m:
* TestFramework/example8.m:
Important change to the START_SET and END_SET macros to stop their use
being confusing. They now both take a simple C-string argument which
names the set, and the macros check that each end matches a start of
the same name. Since tis means that a START_SET no longer takes an
argument sayng whether or notthe set is to be skipped, we now have a
SKIP macro to be used inside a set to skip to the end of it. This
is actually more versatile as we can have multiple SKIP macros in the
same set, each providing a different reason for the set being skipped.
Also removed a few obsolete/unused functions and macros.
2011-01-23 Richard Frith-Macdonald <rfm@gnu.org>
* TestFramework/gnustep-tests.in:

View file

@ -41,7 +41,7 @@
/* Quick test to check that we have the class we expect.
*/
#define TEST_FOR_CLASS(aClassName, aClass, TestDescription) \
pass([aClass isKindOfClass: NSClassFromString(aClassName)], TestDescription)
PASS([aClass isKindOfClass: NSClassFromString(aClassName)], TestDescription)
/* Quick test to check for a non-empty string in the case where we don't
* actually know what value we should be expecting.
@ -54,23 +54,14 @@
&& [_testString length], description); \
}
/* DEPRECATED
* This is for backward compatibility, the original havng been replaced
* by two clearer/simpler macros.
* Please use PASS_EXCEPTION() for a test which is supposed to raise,
* or PASS_RUNS() to test that code runs without raising an exception.
*/
#define TEST_EXCEPTION(code, exceptionName, shouldRaise, description) \
if (shouldRaise) { PASS_EXCEPTION(code, exceptionName, description) } \
else { PASS_RUNS(code, description) }
/* DEPRECATED
/* DEPRECATED ... please use the START_SET/END_SET and PASS macros instead.
START_TEST/END_TEST can be used if the code being tested could raise
and the exception should be considered a test failure. The exception
is not reraised to allow subsequent tests to execute. The START_TEST
macro takes an argument which will skip the test as Skipped if it
evaluates to 0, allowing runtime control of whether the code block
should be executed. */
should be executed.
*/
#define START_TEST(supported) if ((supported)) { NS_DURING
#define END_TEST(result, desc, args...) \
pass(result, desc, ## args); \
@ -80,7 +71,12 @@
[[localException reason] UTF8String], \
[[[localException userInfo] description] UTF8String]); \
pass (NO, desc, ## args); NS_ENDHANDLER } \
else unsupported (desc, ## args)
else { fprintf(stderr, "Failed test: " desc, ## args); \
fprintf(stderr, "\n"); }
/* Functions to test basic capabilities expected of most classes.
*/
@ -215,31 +211,33 @@ static void test_NSCoding(NSArray *objects)
int i;
for (i = 0; i < [objects count]; i++)
{
char buf[100];
id obj = [objects objectAtIndex: i];
const char *prefix;
NSMutableData *data;
NSArchiver *archiver;
id decoded;
START_SET(YES);
pass([[[obj class] description] length],
"I can extract a class name for object");
sprintf(buf, "test_NSCoding object %u", i);
START_SET(buf)
pass([[[obj class] description] length],
"I can extract a class name for object");
prefix = [[NSString stringWithFormat: @"Object %i of class '%s'", i,
[NSStringFromClass([obj class]) UTF8String]] UTF8String];
pass([obj conformsToProtocol: @protocol(NSCoding)],
"conforms to NSCoding protocol");
data = (NSMutableData *)[NSMutableData data];
archiver = [[NSArchiver alloc] initForWritingWithMutableData: data];
pass(archiver != nil, "I am able to set up an archiver");
data = nil;
[archiver encodeRootObject: obj];
data = [archiver archiverData];
pass(data && [data length] > 0, "%s can be encoded", prefix);
decoded = [NSUnarchiver unarchiveObjectWithData: data];
pass(decoded != nil, "can be decoded");
pass([decoded isEqual: obj], "decoded object equals the original");
END_SET("test_NSCoding object %u", i);
prefix = [[NSString stringWithFormat: @"Object %i of class '%s'", i,
[NSStringFromClass([obj class]) UTF8String]] UTF8String];
pass([obj conformsToProtocol: @protocol(NSCoding)],
"conforms to NSCoding protocol");
data = (NSMutableData *)[NSMutableData data];
archiver = [[NSArchiver alloc] initForWritingWithMutableData: data];
pass(archiver != nil, "I am able to set up an archiver");
data = nil;
[archiver encodeRootObject: obj];
data = [archiver archiverData];
pass(data && [data length] > 0, "%s can be encoded", prefix);
decoded = [NSUnarchiver unarchiveObjectWithData: data];
pass(decoded != nil, "can be decoded");
pass([decoded isEqual: obj], "decoded object equals the original");
END_SET(buf)
}
}
@ -248,25 +246,27 @@ static void test_keyed_NSCoding(NSArray *objects)
int i;
for (i = 0; i < [objects count]; i++)
{
char buf[100];
id obj = [objects objectAtIndex: i];
const char *prefix;
NSData *data;
id decoded;
START_SET(YES);
pass([[[obj class] description] length],
"I can extract a class name for object");
sprintf(buf, "test_keyed_NSCoding object %u", i);
START_SET(buf)
pass([[[obj class] description] length],
"I can extract a class name for object");
prefix = [[NSString stringWithFormat: @"Object %i of class '%s'", i,
[NSStringFromClass([obj class]) UTF8String]] UTF8String];
pass([obj conformsToProtocol: @protocol(NSCoding)],
"conforms to NSCoding protocol");
data = [NSKeyedArchiver archivedDataWithRootObject: obj];
pass([data length] > 0, "%s can be encoded", prefix);
decoded = [NSKeyedUnarchiver unarchiveObjectWithData: data];
pass (decoded != nil, "can be decoded");
PASS_EQUAL(decoded, obj, "decoded object equals the original");
END_SET("test_keyed_NSCoding object %u", i);
prefix = [[NSString stringWithFormat: @"Object %i of class '%s'", i,
[NSStringFromClass([obj class]) UTF8String]] UTF8String];
pass([obj conformsToProtocol: @protocol(NSCoding)],
"conforms to NSCoding protocol");
data = [NSKeyedArchiver archivedDataWithRootObject: obj];
pass([data length] > 0, "%s can be encoded", prefix);
decoded = [NSKeyedUnarchiver unarchiveObjectWithData: data];
pass (decoded != nil, "can be decoded");
PASS_EQUAL(decoded, obj, "decoded object equals the original")
END_SET(buf)
}
}
@ -286,6 +286,7 @@ static void test_NSCopying(NSString *iClassName,
for (i = 0; i < [objects count]; i++)
{
char buf[100];
BOOL immutable;
NSString *theName;
const char *prefix;
@ -293,71 +294,73 @@ static void test_NSCopying(NSString *iClassName,
Class theClass = Nil;
id theObj = [objects objectAtIndex: i];
START_SET(YES);
if (iClass != mClass && [theObj isKindOfClass: mClass])
{
immutable = NO;
theName = iClassName;
theClass = iClass;
}
else
{
immutable = YES;
theName = mClassName;
theClass = mClass;
}
prefix = [[NSString stringWithFormat: @"Object %i of class '%s'",
i, [theName UTF8String]] UTF8String];
pass([theObj conformsToProtocol: @protocol(NSCopying)],
"conforms to NSCopying");
theCopy = [theObj copy];
pass(theCopy != nil, "%s understands -copy", prefix);
pass([theCopy isKindOfClass: iClass],
"%s copy is of correct type", prefix);
pass([theObj isEqual: theCopy], "%s original and copy are equal", prefix);
if (immutable)
{
if (YES == mustRetain)
{
pass(theCopy == theObj,
"%s is retained by copy with same zone", prefix);
}
else if (YES == mustCopy)
{
pass(theCopy != theObj,
"%s is not retained by copy with same zone", prefix);
}
}
if (theClass != iClass)
{
pass(![theCopy isKindOfClass: theClass],
"%s result of copy is not immutable", prefix);
}
theCopy = [theObj copyWithZone: testZone];
pass(theCopy != nil, "%s understands -copyWithZone", prefix);
pass([theCopy isKindOfClass: iClass],
"%s zCopy has correct type", prefix);
pass([theObj isEqual: theCopy],
"%s copy and original are equal", prefix);
if (immutable)
{
if (YES == mustRetain)
{
pass(theCopy == theObj,
"%s is retained by copy with other zone", prefix);
}
else if (YES == mustCopy)
{
pass(theCopy != theObj,
"%s is not retained by copy with other zone", prefix);
}
}
if (theClass != iClass)
pass(![theCopy isKindOfClass: theClass],
"%s result of copyWithZone: is not immutable", prefix);
END_SET("test_NSCopying object %u", i);
sprintf(buf, "test_NSCopying object %u", i);
START_SET(buf)
if (iClass != mClass && [theObj isKindOfClass: mClass])
{
immutable = NO;
theName = iClassName;
theClass = iClass;
}
else
{
immutable = YES;
theName = mClassName;
theClass = mClass;
}
prefix = [[NSString stringWithFormat: @"Object %i of class '%s'",
i, [theName UTF8String]] UTF8String];
pass([theObj conformsToProtocol: @protocol(NSCopying)],
"conforms to NSCopying");
theCopy = [theObj copy];
pass(theCopy != nil, "%s understands -copy", prefix);
pass([theCopy isKindOfClass: iClass],
"%s copy is of correct type", prefix);
pass([theObj isEqual: theCopy],
"%s original and copy are equal", prefix);
if (immutable)
{
if (YES == mustRetain)
{
pass(theCopy == theObj,
"%s is retained by copy with same zone", prefix);
}
else if (YES == mustCopy)
{
pass(theCopy != theObj,
"%s is not retained by copy with same zone", prefix);
}
}
if (theClass != iClass)
{
pass(![theCopy isKindOfClass: theClass],
"%s result of copy is not immutable", prefix);
}
theCopy = [theObj copyWithZone: testZone];
pass(theCopy != nil, "%s understands -copyWithZone", prefix);
pass([theCopy isKindOfClass: iClass],
"%s zCopy has correct type", prefix);
pass([theObj isEqual: theCopy],
"%s copy and original are equal", prefix);
if (immutable)
{
if (YES == mustRetain)
{
pass(theCopy == theObj,
"%s is retained by copy with other zone", prefix);
}
else if (YES == mustCopy)
{
pass(theCopy != theObj,
"%s is not retained by copy with other zone", prefix);
}
}
if (theClass != iClass)
pass(![theCopy isKindOfClass: theClass],
"%s result of copyWithZone: is not immutable", prefix);
END_SET(buf)
}
}
@ -378,6 +381,7 @@ static void test_NSMutableCopying(NSString *iClassName,
for (i = 0; i < [objects count]; i++)
{
char buf[100];
id theObj = [objects objectAtIndex: i];
NSString *theName = nil;
const char *prefix;
@ -385,42 +389,43 @@ static void test_NSMutableCopying(NSString *iClassName,
id theCopy = nil;
Class theClass = Nil;
START_SET(YES);
if (iClass == mClass && [theObj isKindOfClass: mClass])
immutable = NO;
else
immutable = YES;
if (immutable)
{
theName = iClassName;
theClass = iClass;
}
else
{
theName = mClassName;
theClass = mClass;
}
prefix = [[NSString stringWithFormat:
@"Object %i of class '%s'", i, [theName UTF8String]] UTF8String];
pass([theObj conformsToProtocol: @protocol(NSMutableCopying)],
"%s conforms to NSMutableCopying protocol", prefix);
theCopy = [theObj mutableCopy];
pass(theCopy != nil, "%s understands -mutableCopy", prefix);
pass([theCopy isKindOfClass: mClass],
"%s mutable copy is of correct type", prefix);
pass([theCopy isEqual: theObj], "%s copy equals original", prefix);
pass(theCopy != theObj,
"%s not retained by mutable copy in the same zone",
[mClassName UTF8String]);
theCopy = [theObj mutableCopyWithZone: testZone];
pass(theCopy != nil,
"%s understands mutableCopyWithZone", [mClassName UTF8String]);
pass(theCopy != theObj, "%s not retained by mutable copy in other zone",
[mClassName UTF8String]);
END_SET("test_NSMutableCopying object %u", i);
sprintf(buf, "test_NSMutableCopying object %u", i);
START_SET(buf);
if (iClass == mClass && [theObj isKindOfClass: mClass])
immutable = NO;
else
immutable = YES;
if (immutable)
{
theName = iClassName;
theClass = iClass;
}
else
{
theName = mClassName;
theClass = mClass;
}
prefix = [[NSString stringWithFormat:
@"Object %i of class '%s'", i, [theName UTF8String]] UTF8String];
pass([theObj conformsToProtocol: @protocol(NSMutableCopying)],
"%s conforms to NSMutableCopying protocol", prefix);
theCopy = [theObj mutableCopy];
pass(theCopy != nil, "%s understands -mutableCopy", prefix);
pass([theCopy isKindOfClass: mClass],
"%s mutable copy is of correct type", prefix);
pass([theCopy isEqual: theObj], "%s copy equals original", prefix);
pass(theCopy != theObj,
"%s not retained by mutable copy in the same zone",
[mClassName UTF8String]);
theCopy = [theObj mutableCopyWithZone: testZone];
pass(theCopy != nil,
"%s understands mutableCopyWithZone", [mClassName UTF8String]);
pass(theCopy != theObj, "%s not retained by mutable copy in other zone",
[mClassName UTF8String]);
END_SET(buf)
}
}

View file

@ -181,8 +181,8 @@ paired calls to the START_SET and END_SET macros. Any setting of testHopeful
within a set is automatically restored at the end of a set, so it makes sense
to group hopes together in a set.
You can skip an entire set by supplying NO as the argument to the START_SET
macro, in which case the entire set will be reported as being Skipped.
You can skip an entire set by calling the SKIP() macro just after the start,
in which case the entire set will be reported as being Skipped.
It is appropriate to skip sets of tests if you have checked and found that
some feature you are testing is not available in the version of the package
under test.

View file

@ -120,42 +120,6 @@ static void testStart()
return;
}
/* The unresolved() function is called with a single string argument to
* notify the testsuite that a test failed to complete for some reason.
* eg. You might call this if an earlier testcase failed and it makes no
* sense to run subsequent tests.
* This is called if a set is terminated before all the tests in it have
* been run.
*/
static void unresolved(const char *format, ...) __attribute__((unused)) __attribute__ ((format(printf, 1, 2), unused));
static void unresolved(const char *format, ...)
{
va_list args;
va_start(args, format);
fprintf(stderr, "Failed set: ");
vfprintf(stderr, format, args);
fprintf(stderr, "\n");
va_end(args);
#if defined(FAILFAST)
exit(1); // Abandon testing now.
#endif
}
/* The unsupported() function is called with a single string argument to
* notify the testsuite that a test could not be run because the capability
* it is testing does not exist on the current platform.
*/
static void unsupported(const char *format, ...) __attribute__((unused)) __attribute__ ((format(printf, 1, 2), unused));
static void unsupported(const char *format, ...)
{
va_list args;
va_start(args, format);
fprintf(stderr, "Skipped set: ");
vfprintf(stderr, format, args);
fprintf(stderr, "\n");
va_end(args);
}
/* Tests a code expression which evaluates to an integer value.
* The expression may not contain commas unless it is bracketed.
* The format must be a literal string printf style format.
@ -295,62 +259,93 @@ static void unsupported(const char *format, ...)
* the scope of the current test but could raise exceptions that should
* be caught to allow further tests to run.
*
* You must pass a 'supported' flag to say whether the code should be run
* or not, if not then the set is reported as unsupported.
* You must pass a short description to identify the set at both its
* start and its end. This allows the seat to be easily identified in the
* log, and also allows for checking to be sure that each start if a set
* is matched by a corresponding end.
*
* The state of the 'testHopeful' flag is saved at the start of the set and
* restored at the end of the set, so you can start your code by setting
* 'testHopeful=YES;' to mark any tests within the set as being part of a group
* of tests we don't expect to pass.
* 'testHopeful=YES;' to mark any tests within the set as being part of a
* group of tests we don't expect to pass.
*
* Importantly, you may skip some or all of the tests in a set if those
* tests are not supported in the package being tested (eg. testing of
* functionality which depends on some external library which was not
* available when the package being tested was buit).
*
* Any uncaught exception occurring inside a set will abort the entire set
* so that remaining tests in the set will not be executed, but you may
* also abandon remaining tests upon any test failure.
*
* The tests within the set are enclosed in an autorelease pool, and any
* temporary objects are cleaned up at the end of the set.
*/
/* The START_SET() macro starts a set of grouped tests or, if the argument
* is false, skips the set and reports the set as unsupported.
/* The START_SET() macro starts a set of grouped tests. It must be matched
* by a corresponding END_SET() with the same string as an argument.
* The argument is a short description to be printed in the log on entry.
*/
#define START_SET(supported) \
if ((supported)) \
{ \
BOOL save_hopeful = testHopeful; \
NS_DURING \
NSAutoreleasePool *_setPool = [NSAutoreleasePool new]; \
{
#define START_SET(setName) \
{ \
BOOL _save_hopeful = testHopeful; \
int _save_line = __LINE__; \
char *_save_set = malloc(strlen(setName) + 1); \
strcpy(_save_set, setName); \
fprintf(stderr, "Start set: %s:%d ... %s\n", \
__FILE__, __LINE__, _save_set); \
fprintf(stderr, "\n"); \
NS_DURING \
NSAutoreleasePool *_setPool = [NSAutoreleasePool new]; \
{
/* The END_SET() macro terminates a set of grouped tests. It's argument is
* a literal printf style format string and variable arguments to print a
* message giving the reason for skipping the set. This should be a short
* message (for immediate display), preferably with a more detailed
* explanation on subsequent lines.
/* The END_SET() macro terminates a set of grouped tests. It must be matched
* by a corresponding START_SET() with the same string as an argument.
* The argument is a short description to be printed in the log on entry.
*/
#define END_SET(format, ...) \
#define END_SET(setName) \
} \
[_setPool release]; \
NS_HANDLER \
if (YES == [[localException name] isEqualToString: @"SkipSet"]) \
{ \
fprintf(stderr, "Skipped set: %s\n", \
[[localException reason] UTF8String]); \
} \
[_setPool release]; \
NS_HANDLER \
if (NO == [[localException name] isEqualToString: @"CheckSet"]) \
{ \
fprintf(stderr, "EXCEPTION: %s %s %s\n", \
[[localException name] UTF8String], \
[[localException reason] UTF8String], \
[[[localException userInfo] description] UTF8String]); \
} \
unresolved("%s:%d ... problem occurred inside set.", \
__FILE__, __LINE__); \
NS_ENDHANDLER \
testHopeful = save_hopeful; \
} \
else \
{ \
unsupported("%s:%d ... " format, __FILE__, __LINE__, ## __VA_ARGS__); \
}
else \
{ \
if (YES == [[localException name] isEqualToString: @"FailSet"]) \
{ \
fprintf(stderr, \
"Failed set: %s:%d ... need not met in %s.\n", \
__FILE__, _save_line, _save_set); \
} \
else \
{ \
fprintf(stderr, "EXCEPTION: %s %s %s\n", \
[[localException name] UTF8String], \
[[localException reason] UTF8String], \
[[[localException userInfo] description] UTF8String]); \
fprintf(stderr, "Failed set: %s:%d ... problem in %s.\n", \
__FILE__, _save_line, _save_set); \
} \
} \
NS_ENDHANDLER \
fprintf(stderr, "End set: %s:%d ... %s\n", \
__FILE__, __LINE__, _save_set); \
if (strcmp(_save_set, setName) != 0) \
fprintf(stderr, "Failed set: %s:%d ... END(%s) with START(%s).\n", \
__FILE__, __LINE__, setName, _save_set); \
free(_save_set); \
testHopeful = _save_hopeful; \
}
/* The NEED macro takes a test macro as an argument and breaks out of a set
* and reports it as failed if the test does not pass.
*/
#define NEED(testToTry) \
testToTry \
{testToTry;} \
if (NO == testPassed) \
{ \
if (nil != testRaised) \
@ -359,10 +354,20 @@ static void unsupported(const char *format, ...)
} \
else \
{ \
[NSException raise: @"CheckSet" format: @"Test did not pass"]; \
[NSException raise: @"FailSet" format: @"Test did not pass"]; \
} \
}
/* The SKIP() macro skips the remainder of a set of grouped tests.
* Its argument is a literal printf style format string and variable
* arguments to print a message giving the reason for skipping the set.
* This should be a short one line message (for immediate display),
* preferably with a more detailed explanation on subsequent lines.
*/
#define SKIP(fmt, ...) \
[NSException raise: @"SkipSet" format: @"%s %d ... " fmt, \
__FILE__, __LINE__, ## __VA_ARGS__];
/* some good macros to compare floating point numbers */
#import <math.h>

View file

@ -11,7 +11,7 @@ main()
/* We start a set here ...
* Having a set means we do not need to bother creating an autorelease pool.
*/
START_SET(YES)
START_SET("example set")
pass(1 == 1, "integer equality works");
pass([[NSObject new] autorelease] != nil, "+new creates an object");

View file

@ -16,7 +16,7 @@ main()
/* We start a set here ...
* Having a set means we do not need to bother creating an autorelease pool.
*/
START_SET(YES)
START_SET("example set")
/* We use a macro here so that any exception in the expression we use
* will not break out of the set, and the two remaining tests will be

View file

@ -13,7 +13,7 @@
int
main()
{
START_SET(YES)
START_SET("example set")
/* We test for the code fragment raising an exception. We don't care
* about the particular exception, so we pass nil as the expected exception

View file

@ -8,7 +8,7 @@
int
main()
{
START_SET(YES)
START_SET("example set")
/* First set a flag to say that we are not expecting tests to
* actually pass.

View file

@ -8,7 +8,7 @@
int
main()
{
START_SET(YES)
START_SET("example set")
/* First set a flag to say that we are not expecting tests to
* actually pass.

View file

@ -10,7 +10,7 @@ main()
{
/* Start a set.
*/
START_SET(YES)
START_SET("outer set")
/* Our first test in this set will pass.
*/
@ -18,7 +18,7 @@ main()
/* Now we start a set nested inside the first one.
*/
START_SET(YES)
START_SET("inner set")
/* And we say we need a test to pass, but it's actually a faulty one
* which will fail, causing the set to be terminated.

View file

@ -11,7 +11,7 @@ main()
{
/* Start a set.
*/
START_SET(YES)
START_SET("example set")
/* Here we demonstrate that the 'expression' evaluated by the PASS
* macro can actually be an arbitrarily complex piece of code as
@ -27,7 +27,7 @@ main()
NSEqualRanges(r, NSMakeRange(1, 10));
}), "a long code-fragment/expression works")
END_SET("test set")
END_SET("example set")
return 0;
}

View file

@ -1,7 +1,7 @@
#import "Testing.h"
#import <NSFoundation/NSGeometry.h>
/* A ninth test ... unsupported tests
/* A ninth test ... skipping unsupported tests
*
* If you run the test with 'gnustep-tests example9.m' it should
* report one set skipped.
@ -11,31 +11,34 @@ main()
{
#define HAVE_XXX NO
/* Start a set, but only if we have the XXX library.
/* Start a set.
*/
START_SET(HAVE_XXX)
START_SET("example set")
/* Here we demonstrate that the 'expression' evaluated by the PASS
* macro can actually be an arbitrarily complex piece of code as
* long as the last statement returns an integral value which can
* be used to represent a pass (non zero) or fail (if zero).
* Where such a code fragment contains commas, it must be written
* inside brackets to let the macro preprocessor know that the whole
* code fragement is the first parameter to the macro.
*/
PASS(({
NSRange r = NSMakeRange(1, 10);
NSEqualRanges(r, NSMakeRange(1, 10));
}), "a long code-fragment/expression works")
/* Here we conditionally skip the set with a message to be displayed.
* The first line will be displayed immediately when the set
* is skipped, and lets the user know that some functionality is missing.
* The remainder of the message is written to the log file so the user
* can find out what to do about the problem.
*/
if (!HAVE_XXX)
SKIP("Feature 'foo' is unsupported.\nThis is because the package was built without the 'XXX' library.\nIf you need 'foo' then please obtain 'XXX' and build and install the package again before re-running this testsuite.")
/* Here we end the set with a message to be displayed if the set is
* skipped. The first line will be displayed immediately when the set
* is skipped, and lets the user know that some functionality is missing.
* The remainder of the message is written to the log file so the user
* can find out what to do about the problem.
*/
END_SET("Feature 'foo' is unsupported.\nThis is because the 'XXX' package was built without the 'YYY' library.\nIf you need 'foo' then please obtain 'YYY' and build and install 'XXX' again before re-running this testsuite.")
/* Here we demonstrate that the 'expression' evaluated by the PASS
* macro can actually be an arbitrarily complex piece of code as
* long as the last statement returns an integral value which can
* be used to represent a pass (non zero) or fail (if zero).
* Where such a code fragment contains commas, it must be written
* inside brackets to let the macro preprocessor know that the whole
* code fragement is the first parameter to the macro.
*/
PASS(({
NSRange r = NSMakeRange(1, 10);
NSEqualRanges(r, NSMakeRange(1, 10));
}), "a long code-fragment/expression works")
END_SET("example set")
return 0;
}