/*!
  @header ECTestSuite
  @abstract Module of Encore
 
  @availability OS X, GNUstep
  @copyright 2004, 2005, 2006 Oliver Langer

  Author: Oliver Langer

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA

  <pre>
  -------------------------------------------------------------------------
  Modification history

  20.11.05 ola     initial version
  22.08.06 ola     license changed
  -------------------------------------------------------------------------
  </pre>
*/

#include <Encore/ECTestSuite.h>
#include <Encore/ECMemory.h>
#include <Encore/ECTestcase.h>
#include <Encore/ECTestResult.h>

@interface ECSelectorHolder : ECObject {
  @private
    SEL method;
}

- initWithSelector: (SEL) aMethod;
- (SEL) selector;
@end


@implementation ECSelectorHolder

- initWithSelector: (SEL) aMethod {
  self = [super init];
  self->method = aMethod;

  return self;
}


- (SEL) selector {
  return self->method;
}
@end


@implementation ECTestSuite

- init {
  self = [super init];

  self->listOfTestcases = [[NSMutableArray alloc] init];
  self->listOfMethodsOfTestcases = [[NSMutableArray alloc] init];
  self->proceedOnFailure = NO;

  return self;
}


- (void) dealloc {
  if( nil != self->listOfTestcases ) {
    [self->listOfMethodsOfTestcases release];
  }

  [super dealloc];
}


- addTestcase: (ECTestcase *) testcaseToAdd 
  withSelector: (SEL) methodToCall {

  [self->listOfTestcases addObject: testcaseToAdd];
  [self->listOfMethodsOfTestcases addObject: 
    [[ECSelectorHolder alloc] initWithSelector: methodToCall]];

  return self;
}


- proceedOnFailure: (BOOL) doIt {
  self->proceedOnFailure = doIt;
  
  return self;
}


- (NSArray *) runTestcases {
  NSMutableArray *testResult = [[NSMutableArray alloc] init];

  NSException *exceptionToThrow = nil;
  BOOL testcaseRanSuccessfully;
  
  EC_AUTORELEASEPOOL_BEGIN
    int i;

    for( i = 0; i < [self->listOfTestcases count]; i++ ) {
      ECTestcase *current 
        = (ECTestcase *) [self->listOfTestcases objectAtIndex: i ];
      ECSelectorHolder *selectorHolder
        = (ECSelectorHolder *) 
          [self->listOfMethodsOfTestcases objectAtIndex: i];

      testcaseRanSuccessfully = YES;
      exceptionToThrow = nil;
      
      NS_DURING
        [current setup];
        [current performSelector: [selectorHolder selector]];
        [testResult 
          addObject: 
            [[ECTestResult alloc] 
              initWithSuccess]];
      NS_HANDLER
        [testResult 
          addObject:
            [[ECTestResult alloc] 
              initWithException: localException]];
        testcaseRanSuccessfully = NO;
        if( !self->proceedOnFailure ) {
          exceptionToThrow = [localException retain];
        }
      NS_ENDHANDLER

      NS_DURING
        [current cleanup];
      NS_HANDLER
        /* hmmm... what to do here? we ignore it at present! */
      NS_ENDHANDLER

      if( !testcaseRanSuccessfully ) {
        if( !self->proceedOnFailure ) {
          if( nil != exceptionToThrow ) {
            [testResult release];
            break;
          }
        }
      }
    }

  EC_AUTORELEASEPOOL_END

  if( nil != exceptionToThrow ) {
    [exceptionToThrow raise];
  }

  return [testResult autorelease];
}
@end
