Skip to content

Commit

Permalink
handle slim exceptions
Browse files Browse the repository at this point in the history
  • Loading branch information
jediwhale committed Feb 23, 2009
1 parent 65f9e69 commit 7d9c436
Show file tree
Hide file tree
Showing 12 changed files with 95 additions and 11 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Expand Up @@ -7,4 +7,4 @@ bin/
obj/
TestResult.xml
*.cache
*.bat
fitnesse*.cmd
1 change: 1 addition & 0 deletions source/fitnesse/fitnesse.csproj
Expand Up @@ -43,6 +43,7 @@
<Compile Include="slim\Messenger.cs" />
<Compile Include="slim\operators\ComposeBoolean.cs" />
<Compile Include="slim\operators\ComposeDefault.cs" />
<Compile Include="slim\operators\ComposeException.cs" />
<Compile Include="slim\operators\ComposeList.cs" />
<Compile Include="slim\operators\ExecuteBase.cs" />
<Compile Include="slim\operators\ExecuteCall.cs" />
Expand Down
1 change: 1 addition & 0 deletions source/fitnesse/slim/Service.cs
Expand Up @@ -21,6 +21,7 @@ public class Service: Processor<string> {
AddOperator(new ParseList());
AddOperator(new ParseSymbol(), 1);
AddOperator(new ComposeDefault());
AddOperator(new ComposeException());
AddOperator(new ComposeBoolean());
AddOperator(new ComposeList());
}
Expand Down
41 changes: 41 additions & 0 deletions source/fitnesse/slim/operators/ComposeException.cs
@@ -0,0 +1,41 @@
// Copyright © Syterra Software Inc. All rights reserved.
// The use and distribution terms for this software are covered by the Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
// which can be found in the file license.txt at the root of this distribution. By using this software in any fashion, you are agreeing
// to be bound by the terms of this license. You must not remove this notice, or any other, from this software.

using System;
using fitnesse.mtee.engine;
using fitnesse.mtee.exception;
using fitnesse.mtee.model;

namespace fitnesse.slim.operators {
public class ComposeException: ComposeOperator<string> {
private const string ExceptionResult = "__EXCEPTION__:{0}";

public bool TryCompose(Processor<string> processor, TypedValue instance, ref Tree<string> result) {
if (!typeof(Exception).IsAssignableFrom(instance.Type)) return false;

if (TryResult<MemberException>(instance,
e => string.Format("NO_METHOD_IN_CLASS {0} {1}", e.MemberName, e.Type), ref result)) return true;

if (TryResult<ConstructorException>(instance,
e => string.Format("NO_CONSTRUCTOR {0}", e.Type), ref result)) return true;

result = MakeResult(instance.Value.ToString());
return true;
}

private delegate string Format<T>(T exception);

private static bool TryResult<T>(TypedValue exception, Format<T> formatter, ref Tree<string> result) where T: class {
var candidateException = exception.Value as T;
if (candidateException == null) return false;
result = MakeResult(string.Format("message<<{0}>> {1}", formatter(candidateException), candidateException));
return true;
}

private static Tree<string> MakeResult(string message) {
return new TreeLeaf<string>(string.Format(ExceptionResult, message));
}
}
}
3 changes: 1 addition & 2 deletions source/fitnesse/slim/operators/ExecuteBase.cs
Expand Up @@ -10,7 +10,6 @@
namespace fitnesse.slim.operators {
public abstract class ExecuteBase: ExecuteOperator<string> {
private const string defaultResult = "OK";
private const string ExceptionResult = "__EXCEPTION__:{0}";
private readonly IdentifierName identifier;

public bool TryExecute(Processor<string> processor, TypedValue instance, Tree<string> parameters, ref TypedValue result) {
Expand All @@ -19,7 +18,7 @@ public abstract class ExecuteBase: ExecuteOperator<string> {
result = new TypedValue(ExecuteOperation(processor, parameters));
}
catch (Exception e) {
result = new TypedValue(Result(parameters, string.Format(ExceptionResult, e)));
result = new TypedValue(Result(parameters, processor.Compose(e)));
}
return true;
}
Expand Down
6 changes: 2 additions & 4 deletions source/mtee/Engine/RuntimeType.cs
Expand Up @@ -23,15 +23,13 @@ public class RuntimeType {

public static RuntimeMember GetInstance(TypedValue instance, string memberName, int parameterCount) {
RuntimeMember runtimeMember = FindInstance(instance.Value, memberName, parameterCount);
if (runtimeMember == null) throw new MemberException(
string.Format("Member '{0}' with {1} parameter(s) not found for type '{2}'.", memberName, parameterCount, instance.Type.FullName));
if (runtimeMember == null) throw new MemberException(instance.Type, memberName, parameterCount);
return runtimeMember;
}

public RuntimeMember GetConstructor(int parameterCount) {
RuntimeMember runtimeMember = FindInstance(Type, ".ctor", parameterCount);
if (runtimeMember == null) throw new MemberException(
string.Format("Constructor with {0} parameter(s) not found for type '{1}'.", parameterCount, Type.FullName));
if (runtimeMember == null) throw new ConstructorException(Type, parameterCount);
return runtimeMember;
}

Expand Down
19 changes: 19 additions & 0 deletions source/mtee/exception/ConstructorException.cs
@@ -0,0 +1,19 @@
// Copyright © Syterra Software Inc. All rights reserved.
// The use and distribution terms for this software are covered by the Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
// which can be found in the file license.txt at the root of this distribution. By using this software in any fashion, you are agreeing
// to be bound by the terms of this license. You must not remove this notice, or any other, from this software.

using System;

namespace fitnesse.mtee.exception {
public class ConstructorException: ApplicationException {
public Type Type { get; private set; }
public int ParameterCount { get; private set; }

public ConstructorException(Type type, int parameterCount)
: base(string.Format("Constructor with {1} parameter(s) not found for type '{0}'.", type.FullName, parameterCount)) {
Type = type;
ParameterCount = parameterCount;
}
}
}
11 changes: 10 additions & 1 deletion source/mtee/exception/MemberException.cs
Expand Up @@ -7,6 +7,15 @@

namespace fitnesse.mtee.exception {
public class MemberException: ApplicationException {
public MemberException(string message): base(message) {}
public Type Type { get; private set; }
public string MemberName { get; private set; }
public int ParameterCount { get; private set; }

public MemberException(Type type, string memberName, int parameterCount)
: base(string.Format("Member '{1}' with {2} parameter(s) not found for type '{0}'.", type.FullName, memberName, parameterCount)) {
Type = type;
MemberName = memberName;
ParameterCount = parameterCount;
}
}
}
1 change: 1 addition & 0 deletions source/mtee/mtee.csproj
Expand Up @@ -44,6 +44,7 @@
<Compile Include="Engine\RuntimeType.cs" />
<Compile Include="Engine\Processor.cs" />
<Compile Include="Engine\Operator.cs" />
<Compile Include="exception\ConstructorException.cs" />
<Compile Include="exception\MemberException.cs" />
<Compile Include="exception\ParseException.cs" />
<Compile Include="Model\Copyable.cs" />
Expand Down
3 changes: 0 additions & 3 deletions source/sample/SlimSamples.cs
Expand Up @@ -23,9 +23,6 @@ public class ShouldIBuyMilk {
public string goToStore() {
return (pints == 0 && (dollars > 2 || creditCard)) ? "yes" : "no";
}

public void execute() {}
public void reset() {}
}

public class EmployeesHiredBefore {
Expand Down
17 changes: 17 additions & 0 deletions source/unitTest/slim/ComposeOperatorsTest.cs
Expand Up @@ -6,6 +6,7 @@
using System;
using System.Collections.Generic;
using fitnesse.mtee.engine;
using fitnesse.mtee.exception;
using fitnesse.mtee.model;
using fitnesse.slim.operators;
using NUnit.Framework;
Expand Down Expand Up @@ -59,12 +60,28 @@ namespace fitnesse.unitTest.slim {
Assert.AreEqual("c", result.Branches[1].Branches[1].Value);
}

[Test] public void ExceptionIsComposed() {
CheckExceptionCompose(new ApplicationException("blah"), string.Empty);
}

[Test] public void MemberExceptionIsComposed() {
CheckExceptionCompose(new MemberException(typeof(string), "garbage", 0), "message<<NO_METHOD_IN_CLASS garbage System.String>> ");
}

[Test] public void ConstructorExceptionIsComposed() {
CheckExceptionCompose(new ConstructorException(typeof(string), 0), "message<<NO_CONSTRUCTOR System.String>> ");
}

private Tree<string> Compose(ComposeOperator<string> composeOperator, object instance, Type type) {
Tree<string> result = null;
Assert.IsTrue(composeOperator.TryCompose(processor, new TypedValue(instance, type), ref result));
return result;
}

private void CheckExceptionCompose(Exception exception, string expected) {
CheckCompose(new ComposeException(), exception, exception.GetType(), string.Format("__EXCEPTION__:{0}{1}", expected, exception));
}

private void CheckCompose(ComposeOperator<string> composeOperator, object instance, Type type, object expected) {
Tree<string> result = null;
Assert.IsTrue(composeOperator.TryCompose(processor, new TypedValue(instance, type), ref result));
Expand Down
1 change: 1 addition & 0 deletions source/unitTest/slim/ExecuteOperatorsTest.cs
Expand Up @@ -17,6 +17,7 @@ namespace fitnesse.unitTest.slim {
[SetUp] public void SetUp() {
processor = new Processor<string>();
processor.AddOperator(new ComposeDefault());
processor.AddOperator(new ComposeException());
processor.AddMemory<SavedInstance>();
processor.AddMemory<Symbol>();
}
Expand Down

0 comments on commit 7d9c436

Please sign in to comment.