Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

moves dispatching functionality out of Fixture class into a Dispatcher class #281

Merged
merged 5 commits into from

4 participants

@MartinGijsen

Ant tells me that all (unit + acceptance) tests pass, so I am reasonably confident I have reached the intended effect without disturbing existing functionality. This is my first ever pull request, but if this works out I hope to contribute some more.

src/fit/FitServer.java
@@ -28,12 +29,16 @@
private boolean sentinel;
public FitServer(String host, int port, boolean verbose) {
+ this();
@benilovj
benilovj added a note

indentation issue here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
src/fit/Fixture.java
((36 lines not shown))
- return d(60000) + ":" + d(10000) + d(1000) + "." + d(100) + d(10);
- }
- }
-
- String d(long scale) {
- long report = elapsed / scale;
- elapsed -= report * scale;
- return Long.toString(report);
- }
- }
-
- // Traversal //////////////////////////
-
- /* Altered by Rick to dispatch on the first Fixture */
-
- public void doTables(Parse tables) {
@benilovj
benilovj added a note

Changing the public interface of Fixture makes me very nervous. Fixture is pretty much the heart of fit, and I suspect there's lots of stuff out there that depends on these methods and might break.

Sorry to make you nervous. Since Fixture is meant to be subclassed, it is of course possible that some people would be affacted by the changes. That is why I only touched the dispatching functionality, which is not something I would expect people to change. (At least I did not need to change anything about the dispatching when creating my fixtures.) Also, the dispatching functionality was hard to understand, which is one of the reasons I felt the code needed some cleaning up but is also another reason why I would expect people not to have touched it. The fact that Fixture does basically two things is another reason I thought it needed some attention. But I am quite open to suggestions.

@benilovj
benilovj added a note

As I said in my other comment, :+1: for splitting Fixture, :-1: for removing public methods.

I'm pretty sure that Fixture#doTables is even documented in the Fit book.

Unless, of course, you feel a change like this is not needed or truly too risky ...

@benilovj
benilovj added a note

If it's just a refactoring, it should be alright.

Too my knowledge, and supported by the successful regression tests,I have not added or removed any functionality. Just shuffled it around.

@benilovj
benilovj added a note

The regression testing doesn't take into account external libraries that depend on Fixture eg DbFit, which I maintain, includes fixtures which subclass Fixture.

So how about I restore the public interface and forward to Dispatcher but deprecate the forwarding methods?

@benilovj
benilovj added a note

Well, I personally would recommend that, but bear in mind that I'm not one of the Fitnesse maintainers, so you might want to wait for final steer from them.

I am eagerly awaiting the views of the FitNesse maintainers.

I guess I am rather used to having all the relevant code available to me when I refactor, which is not exactly the case here. We learn something new every day!

I am attempting to make the new Fixture 'backwards compatible', but it is tricky because that basically means the old design will at least shine through. And I was so hoping to achieve proper seperation of concerns.

BTW: Jake, do you use or override any of the dispatching methods of Fixture in DbFit? In its tests, perhaps?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
src/fitnesse/FitFilter.java
((6 lines not shown))
}
protected void exit() {
output.close();
- System.exit(fixture.counts.wrong + fixture.counts.exceptions);
+// System.exit(fixture.counts.wrong + fixture.counts.exceptions);
@benilovj
benilovj added a note

you probably don't want to leave this commented out here

Nope. Oops.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@benilovj

I think it's definitely a good thing to make the Fixture class smaller, but only if it doesn't change the public interface. The old interface could be preserved by forwarding the calls inside Fixture to Dispatcher.

That way, you shouldn't have to change any of the tests either.

@jediwhale
Collaborator

Nice clean up on Fixture class but the existing public methods must be retained for compatibility - make them just forward to the new classes. Fixture class has been in use for 10+ years and who knows how people may have used it.

MartinGijsen added some commits
@MartinGijsen MartinGijsen reintroduced public members of Fixture class for compatibility 33d5e65
@MartinGijsen MartinGijsen Introduced parent class for Fixture named BaseFixture.
This seems the best way to get a clean fixture (do dispatching)
while also keeping the Fixture class backwards compatible.
ecd0b8d
@MartinGijsen

Because of the particular design of the Fixture class dispatching functionality, it seemed best to separate that functionality from more generic Fixture funtionality by moving the generic functionality to a parent class. This ensures full compatibility for classes that derive from Fixture. It also enables other kinds of fixtures that behave somewhat different.

@amolenaar
Collaborator

Why is there a BaseFixture introduced?

@MartinGijsen

Arjan, please check my earlier comment. It seems the most elegant way to make a new fixture class without dispatching, while retaining backwards compatibility for Fixture. Open to suggestions, though ...

@amolenaar amolenaar merged commit a569f16 into from
@amolenaar
Collaborator

I merged the change. Seems everybody's happy with it ;).

@amolenaar amolenaar referenced this pull request from a commit
@amolenaar amolenaar Revert "Merge pull request #281 from MartinGijsen/master"
This reverts commit 3a943a8, reversing
changes made to 8222ce9.
26da042
@antoine-aumjaud antoine-aumjaud referenced this pull request from a commit in antoine-aumjaud/fitnesse
@amolenaar amolenaar Revert "Merge pull request #281 from MartinGijsen/master"
This reverts commit 3a943a8, reversing
changes made to 8222ce9.
aa747a1
@antoine-aumjaud antoine-aumjaud referenced this pull request from a commit in antoine-aumjaud/fitnesse
@amolenaar amolenaar Merge branch 'fit-revert': reverts Fit changes from #281.
Fixes #359.
8d7dac9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jul 4, 2013
  1. @MartinGijsen
  2. @MartinGijsen
Commits on Jul 6, 2013
  1. @MartinGijsen
  2. @MartinGijsen

    Introduced parent class for Fixture named BaseFixture.

    MartinGijsen authored
    This seems the best way to get a clean fixture (do dispatching)
    while also keeping the Fixture class backwards compatible.
Commits on Jul 8, 2013
  1. @MartinGijsen
This page is out of date. Refresh to see the latest.
View
164 src/fit/BaseFixture.java
@@ -0,0 +1,164 @@
+// Modified or written by Object Mentor, Inc. for inclusion with FitNesse.
+// Copyright (c) 2002 Cunningham & Cunningham, Inc.
+// Released under the terms of the GNU General Public License version 2 or later.package fit;
+
+package fit;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import fit.exception.FitFailureException;
+
+
+public class BaseFixture {
+ public Map<String, Object> summary = new HashMap<String, Object>();
+
+ public Counts counts = new Counts();
+
+ protected String[] args;
+
+
+ protected Class<?> getTargetClass() {
+ return getClass();
+ }
+
+ public static BaseFixture loadFixture(String fixtureName) throws Throwable {
+ return FixtureLoader.instance().disgraceThenLoad(fixtureName);
+ }
+
+ public void getArgsForTable(Parse table) {
+ List<String> argumentList = new ArrayList<String>();
+ Parse parameters = table.parts.parts.more;
+ for (; parameters != null; parameters = parameters.more)
+ argumentList.add(parameters.text());
+
+ args = argumentList.toArray(new String[argumentList.size()]);
+ }
+
+ public void doTable(Parse table) {
+ doRows(table.parts.more);
+ }
+
+ public void doRows(Parse rows) {
+ while (rows != null) {
+ Parse more = rows.more;
+ doRow(rows);
+ rows = more;
+ }
+ }
+
+ public void doRow(Parse row) {
+ doCells(row.parts);
+ }
+
+ public void doCells(Parse cells) {
+ for (int i = 0; cells != null; i++) {
+ try {
+ doCell(cells, i);
+ } catch (Exception e) {
+ exception(cells, e);
+ }
+ cells = cells.more;
+ }
+ }
+
+ public void doCell(Parse cell, int columnNumber) {
+ ignore(cell);
+ }
+
+ // Annotation ///////////////////////////////
+
+ public void right(Parse cell) {
+ cell.addToTag(" class=\"pass\"");
+ counts.right++;
+ }
+
+ public void wrong(Parse cell) {
+ cell.addToTag(" class=\"fail\"");
+ counts.wrong++;
+ }
+
+ public void wrong(Parse cell, String actual) {
+ wrong(cell);
+ cell.addToBody(label("expected") + "<hr>" + escape(actual) + label("actual"));
+ }
+
+ public void ignore(Parse cell) {
+ cell.addToTag(" class=\"ignore\"");
+ counts.ignores++;
+ }
+
+ public void exception(Parse cell, Throwable exception) {
+ while (exception.getClass().equals(InvocationTargetException.class)) {
+ exception = ((InvocationTargetException) exception).getTargetException();
+ }
+ if (isFriendlyException(exception)) {
+ cell.addToBody("<hr/>" + label(exception.getMessage()));
+ } else {
+ final StringWriter buf = new StringWriter();
+ exception.printStackTrace(new PrintWriter(buf));
+ cell.addToBody("<hr><pre><div class=\"fit_stacktrace\">" + (buf.toString()) + "</div></pre>");
+ }
+ cell.addToTag(" class=\"error\"");
+ counts.exceptions++;
+ }
+
+ public boolean isFriendlyException(Throwable exception) {
+ return exception instanceof FitFailureException;
+ }
+
+ // Utility //////////////////////////////////
+
+ public String counts() {
+ return counts.toString();
+ }
+
+ public static String label(String string) {
+ return " <span class=\"fit_label\">" + string + "</span>";
+ }
+
+ public static String gray(String string) {
+ return " <span class=\"fit_grey\">" + string + "</span>";
+ }
+
+ public static String escape(String string) {
+ return escape(escape(string, '&', "&amp;"), '<', "&lt;");
+ }
+
+ public static String escape(String string, char from, String to) {
+ int i = -1;
+ while ((i = string.indexOf(from, i + 1)) >= 0) {
+ if (i == 0) {
+ string = to + string.substring(1);
+ } else if (i == string.length()) {
+ string = string.substring(0, i) + to;
+ } else {
+ string = string.substring(0, i) + to + string.substring(i + 1);
+ }
+ }
+ return string;
+ }
+
+ public static String camel(String name) {
+ StringBuffer b = new StringBuffer(name.length());
+ StringTokenizer t = new StringTokenizer(name);
+ b.append(t.nextToken());
+ while (t.hasMoreTokens()) {
+ String token = t.nextToken();
+ b.append(token.substring(0, 1).toUpperCase()); // replace spaces with camelCase
+ b.append(token.substring(1));
+ }
+ return b.toString();
+ }
+
+ public String[] getArgs() {
+ return Arrays.copyOf(args, args.length);
+ }
+}
View
130 src/fit/Dispatcher.java
@@ -0,0 +1,130 @@
+package fit;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import fit.exception.FitFailureException;
+
+
+public class Dispatcher {
+ public final Map<String, Object> summary;
+ public Counts counts;
+
+ private final FixtureListener listener;
+
+ private static boolean forcedAbort = false; //Semaphores
+
+
+ public static class RunTime {
+ long start = System.currentTimeMillis();
+ long elapsed = 0;
+
+ public String toString() {
+ elapsed = System.currentTimeMillis() - start;
+ if (elapsed > 600000) {
+ return d(3600000) + ":" + d(600000) + d(60000) + ":" + d(10000) + d(1000);
+ } else {
+ return d(60000) + ":" + d(10000) + d(1000) + "." + d(100) + d(10);
+ }
+ }
+
+ String d(long scale) {
+ long report = elapsed / scale;
+ elapsed -= report * scale;
+ return Long.toString(report);
+ }
+ }
+
+ public Dispatcher(FixtureListener listener) {
+ counts = new Counts();
+ summary = new HashMap<String, Object>();
+ this.listener = listener;
+ }
+
+ public Dispatcher() {
+ this(new NullFixtureListener());
+ }
+
+ public static void setForcedAbort(boolean state) {
+ forcedAbort = state;
+ } //Semaphores
+
+ @Deprecated
+ public static boolean aborting() {
+ return forcedAbort;
+ } //Semaphores
+
+ public void doTables(Parse tables) {
+ summary.put("run date", new Date());
+ summary.put("run elapsed time", new RunTime());
+ counts = new Counts();
+ while (tables != null) {
+ processTable(tables);
+ tables = tables.more;
+ }
+ listener.tablesFinished(counts);
+ cleanup();
+ }
+
+ protected void cleanup() {
+ Fixture.ClearSymbols();
+ SemaphoreFixture.ClearSemaphores(); //Semaphores: clear all at end
+ }
+
+ private void processTable(Parse table) {
+ Parse heading = table.at(0, 0, 0);
+ if (forcedAbort) {
+ ignore(heading); //Semaphores: ignore on failed lock
+ } else if (heading != null) {
+ try {
+ BaseFixture fixture = getLinkedFixtureWithArgs(table);
+ fixture.doTable(table);
+ } catch (Throwable e) {
+ exception(heading, e);
+ } finally {
+ listener.tableFinished(table);
+ }
+ }
+ }
+
+ private void ignore(Parse cell) {
+ cell.addToTag(" class=\"ignore\"");
+ counts.ignores++;
+ }
+
+ private BaseFixture getLinkedFixtureWithArgs(Parse tables) throws Throwable {
+ Parse header = tables.at(0, 0, 0);
+ BaseFixture fixture = loadFixture(header.text());
+ fixture.counts = counts;
+ fixture.summary = summary;
+ fixture.getArgsForTable(tables);
+ return fixture;
+ }
+
+ public static BaseFixture loadFixture(String fixtureName) throws Throwable {
+ return FixtureLoader.instance().disgraceThenLoad(fixtureName);
+ }
+
+ public void exception(Parse cell, Throwable exception) {
+ while (exception.getClass().equals(InvocationTargetException.class)) {
+ exception = ((InvocationTargetException) exception).getTargetException();
+ }
+ if (isFriendlyException(exception)) {
+ cell.addToBody("<hr/>" + BaseFixture.label(exception.getMessage()));
+ } else {
+ final StringWriter buf = new StringWriter();
+ exception.printStackTrace(new PrintWriter(buf));
+ cell.addToBody("<hr><pre><div class=\"fit_stacktrace\">" + (buf.toString()) + "</div></pre>");
+ }
+ cell.addToTag(" class=\"error\"");
+ counts.exceptions++;
+ }
+
+ private boolean isFriendlyException(Throwable exception) {
+ return exception instanceof FitFailureException;
+ }
+}
View
57 src/fit/DispatcherTest.java
@@ -0,0 +1,57 @@
+// Copyright (C) 2013 by Object Mentor, Inc. All rights reserved.
+// Released under the terms of the CPL Common Public License version 1.0.
+package fit;
+
+import java.text.ParseException;
+
+import junit.framework.TestCase;
+
+
+public class DispatcherTest extends TestCase {
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testRelationalMatching() throws Exception {
+ final String[][] table = {
+ {"fitnesse.fixtures.ColumnFixtureTestFixture"},
+ {"input", "output?"},
+ {"1", "_>0"}
+ };
+ Parse page = executeFixture(table);
+ String colTwoResult = page.at(0, 2, 1).body;
+ assertTrue(colTwoResult.contains("<b>1</b>>0"));
+ String colTwoTag = page.at(0, 2, 1).tag;
+ assertTrue(colTwoTag.contains("pass"));
+ }
+
+ public static Parse executeFixture(String[][] table) throws ParseException {
+ String pageString = makeFixtureTable(table);
+ Parse page = new Parse(pageString);
+ Dispatcher dispatcher = new Dispatcher();
+ dispatcher.doTables(page);
+ return page;
+ }
+
+ private static String makeFixtureTable(String table[][]) {
+ StringBuffer buf = new StringBuffer();
+ buf.append("<table>\n");
+ for (int ri = 0; ri < table.length; ri++) {
+ buf.append(" <tr>");
+ String[] row = table[ri];
+ for (int ci = 0; ci < row.length; ci++) {
+ String cell = row[ci];
+ buf.append("<td>").append(cell).append("</td>");
+ }
+ buf.append("</tr>\n");
+ }
+ buf.append("</table>\n");
+ return buf.toString();
+ }
+}
View
22 src/fit/FileRunner.java
@@ -17,10 +17,12 @@
public class FileRunner {
public String input;
- public Parse tables;
- public Fixture fixture = new Fixture();
- public PrintWriter output;
+
+ protected Parse tables;
+ protected Dispatcher dispatcher = new Dispatcher();
+ protected PrintWriter output;
+
public static void main(String argv[]) {
new FileRunner().run(argv);
}
@@ -34,7 +36,7 @@ public void run(String argv[]) {
public void process() {
try {
tables = new Parse(input);
- fixture.doTables(tables);
+ dispatcher.doTables(tables);
} catch (Exception e) {
exception(e);
}
@@ -48,9 +50,9 @@ public void args(String[] argv) {
}
File in = new File(argv[0]);
File out = new File(argv[1]);
- fixture.summary.put("input file", in.getAbsolutePath());
- fixture.summary.put("input update", new Date(in.lastModified()));
- fixture.summary.put("output file", out.getAbsolutePath());
+ dispatcher.summary.put("input file", in.getAbsolutePath());
+ dispatcher.summary.put("input update", new Date(in.lastModified()));
+ dispatcher.summary.put("output file", out.getAbsolutePath());
try {
input = read(in);
output = new PrintWriter(new BufferedWriter(new FileWriter(out)));
@@ -70,13 +72,13 @@ protected String read(File input) throws IOException {
protected void exception(Exception e) {
tables = new Parse("body", "Unable to parse input. Input ignored.", null, null);
- fixture.exception(tables, e);
+ dispatcher.exception(tables, e);
}
protected void exit() {
output.close();
- System.err.println(fixture.counts());
- System.exit(fixture.counts.wrong + fixture.counts.exceptions);
+ System.err.println(dispatcher.counts.toString());
+ System.exit(dispatcher.counts.wrong + dispatcher.counts.exceptions);
}
}
View
103 src/fit/FitServer.java
@@ -11,11 +11,12 @@
import util.FileUtil;
import fit.exception.FitParseException;
+
public class FitServer {
- public String input;
- public Fixture fixture = new Fixture();
- public FixtureListener fixtureListener = new TablePrintingFixtureListener();
- private Counts counts = new Counts();
+ private final Dispatcher dispatcher;
+ private final Counts overallCounts;
+ private final FixtureListener fixtureListener;
+
private OutputStream socketOutput;
private StreamReader socketReader;
private boolean verbose = false;
@@ -28,12 +29,16 @@
private boolean sentinel;
public FitServer(String host, int port, boolean verbose) {
+ this();
this.host = host;
this.port = port;
this.verbose = verbose;
}
public FitServer() {
+ fixtureListener = new TablePrintingFixtureListener();
+ dispatcher = new Dispatcher(fixtureListener);
+ overallCounts = new Counts();
}
public static void main(String argv[]) throws Exception {
@@ -60,6 +65,25 @@ public void run(String argv[]) throws Exception {
exit();
}
+ public void args(String[] argv) {
+ CommandLine commandLine = new CommandLine("[-v][-x][-s] host port socketToken");
+ if (commandLine.parse(argv)) {
+ host = commandLine.getArgument("host");
+ port = Integer.parseInt(commandLine.getArgument("port"));
+ socketToken = Integer.parseInt(commandLine.getArgument("socketToken"));
+ verbose = commandLine.hasOption("v");
+ noExit = commandLine.hasOption("x");
+ sentinel = commandLine.hasOption("s");
+ } else
+ usage();
+ }
+
+ private void usage() {
+ System.out.println("usage: java fit.FitServer [-v] host port socketTicket");
+ System.out.println("\t-v\tverbose");
+ System.exit(-1);
+ }
+
public static String sentinelName(int thePort) {
return String.format("fitserverSentinel%d", thePort);
}
@@ -69,7 +93,6 @@ public void closeConnection() throws IOException {
}
public void process() {
- fixture.listener = fixtureListener;
try {
int size = 1;
while ((size = FitProtocol.readSize(socketReader)) != 0) {
@@ -78,68 +101,36 @@ public void process() {
String document = FitProtocol.readDocument(socketReader, size);
//TODO MDM if the page name was always the first line of the body, it could be printed here.
Parse tables = new Parse(document);
- newFixture().doTables(tables);
- print("\tresults: " + fixture.counts() + "\n");
- counts.tally(fixture.counts);
- }
- catch (FitParseException e) {
+ dispatcher.doTables(tables);
+ print("\tresults: " + dispatcher.counts.toString() + "\n");
+ overallCounts.tally(dispatcher.counts);
+ } catch (FitParseException e) {
exception(e);
}
}
print("completion signal recieved" + "\n");
- }
- catch (Exception e) {
+ } catch (Exception e) {
exception(e);
}
}
- public String readDocument() throws Exception {
- int size = FitProtocol.readSize(socketReader);
- return FitProtocol.readDocument(socketReader, size);
- }
-
- protected Fixture newFixture() {
- fixture = new Fixture();
- fixture.listener = fixtureListener;
- return fixture;
- }
-
- public void args(String[] argv) {
- CommandLine commandLine = new CommandLine("[-v][-x][-s] host port socketToken");
- if (commandLine.parse(argv)) {
- host = commandLine.getArgument("host");
- port = Integer.parseInt(commandLine.getArgument("port"));
- socketToken = Integer.parseInt(commandLine.getArgument("socketToken"));
- verbose = commandLine.hasOption("v");
- noExit = commandLine.hasOption("x");
- sentinel = commandLine.hasOption("s");
- } else
- usage();
- }
-
- private void usage() {
- System.out.println("usage: java fit.FitServer [-v] host port socketTicket");
- System.out.println("\t-v\tverbose");
- System.exit(-1);
- }
-
protected void exception(Exception e) {
print("Exception occurred!" + "\n");
print("\t" + e.getMessage() + "\n");
Parse tables = new Parse("span", "Exception occurred: ", null, null);
- fixture.exception(tables, e);
- counts.exceptions += 1;
- fixture.listener.tableFinished(tables);
- fixture.listener.tablesFinished(counts); //TODO shouldn't this be fixture.counts
+ dispatcher.exception(tables, e);
+ overallCounts.exceptions += 1;
+ fixtureListener.tableFinished(tables);
+ fixtureListener.tablesFinished(dispatcher.counts);
}
public void exit() throws Exception {
print("exiting" + "\n");
- print("\tend results: " + counts.toString() + "\n");
+ print("\tend results: " + overallCounts.toString() + "\n");
}
public int exitCode() {
- return counts.wrong + counts.exceptions;
+ return overallCounts.wrong + overallCounts.exceptions;
}
public void establishConnection() throws Exception {
@@ -174,10 +165,6 @@ public void validateConnection() throws Exception {
}
}
- public Counts getCounts() {
- return counts;
- }
-
private void print(String message) {
if (verbose)
System.out.print(message);
@@ -197,19 +184,13 @@ private void print(String message) {
return byteBuffer.toByteArray();
}
- public void writeCounts(Counts count) throws IOException {
- //TODO This can't be right.... which counts should be used?
- FitProtocol.writeCounts(counts, socketOutput);
- }
-
class TablePrintingFixtureListener implements FixtureListener {
public void tableFinished(Parse table) {
try {
byte[] bytes = readTable(table);
if (bytes.length > 0)
FitProtocol.writeData(bytes, socketOutput);
- }
- catch (Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
}
@@ -217,11 +198,9 @@ public void tableFinished(Parse table) {
public void tablesFinished(Counts count) {
try {
FitProtocol.writeCounts(count, socketOutput);
- }
- catch (IOException e) {
+ } catch (IOException e) {
e.printStackTrace();
}
}
}
}
-
View
182 src/fit/Fixture.java
@@ -4,70 +4,39 @@
package fit;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.DateFormat;
import java.text.ParseException;
-import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
-import java.util.StringTokenizer;
import fit.exception.CouldNotParseFitFailureException;
import fit.exception.FitFailureException;
import fit.exception.FitMatcherException;
-// TODO-RcM Figure out how to make me smaller.
-public class Fixture {
- public Map<String, Object> summary = new HashMap<String, Object>();
-
- public Counts counts = new Counts();
+public class Fixture extends BaseFixture {
+ @Deprecated
public FixtureListener listener = new NullFixtureListener();
- protected String[] args;
-
private static final Map<String, Object> symbols = new HashMap<String, Object>();
- private static boolean forcedAbort = false; //Semaphores
+
+ @Deprecated
public static void setForcedAbort(boolean state) {
- forcedAbort = state;
+ Dispatcher.setForcedAbort(state);
} //Semaphores
protected Class<?> getTargetClass() {
return getClass();
}
- public class RunTime {
- long start = System.currentTimeMillis();
-
- long elapsed = 0;
-
- public String toString() {
- elapsed = System.currentTimeMillis() - start;
- if (elapsed > 600000) {
- return d(3600000) + ":" + d(600000) + d(60000) + ":" + d(10000) + d(1000);
- } else {
- return d(60000) + ":" + d(10000) + d(1000) + "." + d(100) + d(10);
- }
- }
-
- String d(long scale) {
- long report = elapsed / scale;
- elapsed -= report * scale;
- return Long.toString(report);
- }
- }
+ @Deprecated
+ public class RunTime extends Dispatcher.RunTime { }
// Traversal //////////////////////////
-
- /* Altered by Rick to dispatch on the first Fixture */
-
+ @Deprecated
public void doTables(Parse tables) {
summary.put("run date", new Date());
summary.put("run elapsed time", new RunTime());
@@ -93,7 +62,7 @@ public static void ClearSymbols() {
symbols.clear();
}
- /* Added by Rick to allow a dispatch into DoFixture */
+ @Deprecated
protected void interpretTables(Parse tables) {
try { // Don't create the first fixture again, because creation may do something important.
getArgsForTable(tables); // get them again for the new fixture object
@@ -106,17 +75,17 @@ protected void interpretTables(Parse tables) {
interpretFollowingTables(tables);
}
- /* Added by Rick */
+ @Deprecated
private void interpretFollowingTables(Parse tables) {
listener.tableFinished(tables);
tables = tables.more;
while (tables != null) {
Parse heading = tables.at(0, 0, 0);
- if (forcedAbort) ignore(heading); //Semaphores: ignore on failed lock
+ if (Dispatcher.aborting()) ignore(heading); //Semaphores: ignore on failed lock
else if (heading != null) {
try {
- Fixture fixture = getLinkedFixtureWithArgs(tables);
+ BaseFixture fixture = getLinkedFixtureWithArgs(tables);
fixture.doTable(tables);
} catch (Throwable e) {
exception(heading, e);
@@ -127,7 +96,7 @@ else if (heading != null) {
}
}
- /* Added by Rick */
+ @Deprecated
protected Fixture getLinkedFixtureWithArgs(Parse tables) throws Throwable {
Parse header = tables.at(0, 0, 0);
Fixture fixture = loadFixture(header.text());
@@ -138,133 +107,34 @@ protected Fixture getLinkedFixtureWithArgs(Parse tables) throws Throwable {
}
public static Fixture loadFixture(String fixtureName) throws Throwable {
- return FixtureLoader.instance().disgraceThenLoad(fixtureName);
- }
-
- public void getArgsForTable(Parse table) {
- List<String> argumentList = new ArrayList<String>();
- Parse parameters = table.parts.parts.more;
- for (; parameters != null; parameters = parameters.more)
- argumentList.add(parameters.text());
-
- args = argumentList.toArray(new String[argumentList.size()]);
- }
-
- public void doTable(Parse table) {
- doRows(table.parts.more);
- }
-
- public void doRows(Parse rows) {
- while (rows != null) {
- Parse more = rows.more;
- doRow(rows);
- rows = more;
- }
- }
-
- public void doRow(Parse row) {
- doCells(row.parts);
- }
-
- public void doCells(Parse cells) {
- for (int i = 0; cells != null; i++) {
- try {
- doCell(cells, i);
- } catch (Exception e) {
- exception(cells, e);
- }
- cells = cells.more;
- }
- }
-
- public void doCell(Parse cell, int columnNumber) {
- ignore(cell);
- }
-
- // Annotation ///////////////////////////////
-
- public void right(Parse cell) {
- cell.addToTag(" class=\"pass\"");
- counts.right++;
- }
-
- public void wrong(Parse cell) {
- cell.addToTag(" class=\"fail\"");
- counts.wrong++;
- }
-
- public void wrong(Parse cell, String actual) {
- wrong(cell);
- cell.addToBody(label("expected") + "<hr>" + escape(actual) + label("actual"));
- }
-
- public void ignore(Parse cell) {
- cell.addToTag(" class=\"ignore\"");
- counts.ignores++;
- }
-
- public void exception(Parse cell, Throwable exception) {
- while (exception.getClass().equals(InvocationTargetException.class)) {
- exception = ((InvocationTargetException) exception).getTargetException();
- }
- if (isFriendlyException(exception)) {
- cell.addToBody("<hr/>" + label(exception.getMessage()));
- } else {
- final StringWriter buf = new StringWriter();
- exception.printStackTrace(new PrintWriter(buf));
- cell.addToBody("<hr><pre><div class=\"fit_stacktrace\">" + (buf.toString()) + "</div></pre>");
- }
- cell.addToTag(" class=\"error\"");
- counts.exceptions++;
- }
-
- public boolean isFriendlyException(Throwable exception) {
- return exception instanceof FitFailureException;
+ return (Fixture) BaseFixture.loadFixture(fixtureName);
}
// Utility //////////////////////////////////
- public String counts() {
- return counts.toString();
- }
-
+ @Deprecated
public static String label(String string) {
- return " <span class=\"fit_label\">" + string + "</span>";
+ return BaseFixture.label(string);
}
+ @Deprecated
public static String gray(String string) {
- return " <span class=\"fit_grey\">" + string + "</span>";
+ return BaseFixture.gray(string);
}
+ @Deprecated
public static String escape(String string) {
- return escape(escape(string, '&', "&amp;"), '<', "&lt;");
+ return BaseFixture.escape(string);
}
+ @Deprecated
public static String escape(String string, char from, String to) {
- int i = -1;
- while ((i = string.indexOf(from, i + 1)) >= 0) {
- if (i == 0) {
- string = to + string.substring(1);
- } else if (i == string.length()) {
- string = string.substring(0, i) + to;
- } else {
- string = string.substring(0, i) + to + string.substring(i + 1);
- }
- }
- return string;
+ return BaseFixture.escape(string, from, to);
}
+ @Deprecated
public static String camel(String name) {
- StringBuffer b = new StringBuffer(name.length());
- StringTokenizer t = new StringTokenizer(name);
- b.append(t.nextToken());
- while (t.hasMoreTokens()) {
- String token = t.nextToken();
- b.append(token.substring(0, 1).toUpperCase()); // replace spaces with
- // camelCase
- b.append(token.substring(1));
- }
- return b.toString();
+ return BaseFixture.camel(name);
}
public Object parse(String s, Class<?> type) throws Exception {
@@ -319,10 +189,6 @@ private void handleErrorInCell(TypeAdapter a, Parse cell) {
}
}
- public String[] getArgs() {
- return Arrays.copyOf(args, args.length);
- }
-
public static void setSymbol(String name, Object value) {
symbols.put(name, (value == null) ? "null" : value);
}
View
6 src/fit/FixtureClass.java
@@ -13,7 +13,7 @@ public FixtureClass(Class<?> klass) {
this.klass = klass;
}
- public Fixture newInstance() throws IllegalAccessException {
+ public BaseFixture newInstance() throws IllegalAccessException {
// Instantiate according to policies?
// Example: policy #1 -- has default constructor
// ...
@@ -23,8 +23,8 @@ public Fixture newInstance() throws IllegalAccessException {
try {
Object fixtureAsObject = klass.newInstance();
- if (fixtureAsObject instanceof Fixture) {
- return (Fixture) fixtureAsObject;
+ if (fixtureAsObject instanceof BaseFixture) {
+ return (BaseFixture) fixtureAsObject;
} else {
throw new ClassIsNotFixtureException(fixtureClassName);
}
View
10 src/fit/FixtureLoader.java
@@ -39,14 +39,14 @@ public static void setInstance(FixtureLoader loader) {
}
};
- public Fixture disgraceThenLoad(String tableName) throws Throwable {
+ public BaseFixture disgraceThenLoad(String tableName) throws Throwable {
FixtureName fixtureName = new FixtureName(tableName);
- Fixture fixture = instantiateFirstValidFixtureClass(fixtureName);
+ BaseFixture fixture = instantiateFirstValidFixtureClass(fixtureName);
addPackageToFixturePath(fixture);
return fixture;
}
- private void addPackageToFixturePath(Fixture fixture) {
+ private void addPackageToFixturePath(BaseFixture fixture) {
Package fixturePackage = fixture.getClass().getPackage();
if (fixturePackage != null)
addPackageToPath(fixturePackage.getName());
@@ -56,7 +56,7 @@ public void addPackageToPath(String name) {
fixturePathElements.add(name);
}
- private Fixture instantiateFixture(String fixtureName) throws Throwable {
+ private BaseFixture instantiateFixture(String fixtureName) throws Throwable {
Class<?> classForFixture = loadFixtureClass(fixtureName);
FixtureClass fixtureClass = new FixtureClass(classForFixture);
return fixtureClass.newInstance();
@@ -75,7 +75,7 @@ private Fixture instantiateFixture(String fixtureName) throws Throwable {
}
}
- private Fixture instantiateFirstValidFixtureClass(FixtureName fixtureName)
+ private BaseFixture instantiateFirstValidFixtureClass(FixtureName fixtureName)
throws Throwable {
for (Iterator<String> i = fixtureName.getPotentialFixtureClassNames(
fixturePathElements).iterator(); i.hasNext();) {
View
8 src/fit/FixtureLoaderTest.java
@@ -17,21 +17,21 @@ protected void setUp() throws Exception {
public void testLoadFixturesFromPreviouslyRememberedPackages()
throws Throwable {
- Fixture f1 = fixtureLoader.disgraceThenLoad("fit.FixtureOne");
+ BaseFixture f1 = fixtureLoader.disgraceThenLoad("fit.FixtureOne");
assertEquals("fit.FixtureOne", f1.getClass().getName());
- Fixture f2 = fixtureLoader.disgraceThenLoad("FixtureTwo");
+ BaseFixture f2 = fixtureLoader.disgraceThenLoad("FixtureTwo");
assertEquals("fit.FixtureTwo", f2.getClass().getName());
}
public void testLoadFixturesWithGracefulName() throws Throwable {
fixtureLoader.disgraceThenLoad("fit.FixtureOne");
- Fixture f2 = fixtureLoader.disgraceThenLoad("fixture two");
+ BaseFixture f2 = fixtureLoader.disgraceThenLoad("fixture two");
assertEquals("fit.FixtureTwo", f2.getClass().getName());
}
public void testLoadFixturesWithFixtureImplied() throws Throwable {
fixtureLoader.disgraceThenLoad("fit.TheThirdFixture");
- Fixture fixture = fixtureLoader.disgraceThenLoad("the third");
+ BaseFixture fixture = fixtureLoader.disgraceThenLoad("the third");
assertEquals("fit.TheThirdFixture", fixture.getClass().getName());
}
}
View
4 src/fit/FriendlyErrorTest.java
@@ -11,8 +11,8 @@
public void testCantFindFixture() throws Exception {
String pageString = "<table><tr><td>NoSuchFixture</td></tr></table>";
Parse page = new Parse(pageString);
- Fixture fixture = new Fixture();
- fixture.doTables(page);
+ Dispatcher dispatcher = new Dispatcher();
+ dispatcher.doTables(page);
String fixtureName = page.at(0, 0, 0).body;
assertTrue(fixtureName.contains("Could not find fixture: NoSuchFixture."));
}
View
2  src/fit/SemaphoreFixture.java
@@ -24,7 +24,7 @@ private void doActionOnSemaphore(String action, String name, Parse infoCells) {
boolean isOk = false;
if ("lock".equals(action)) {
isOk = lockSemaphore(name);
- if (!isOk) setForcedAbort(true);
+ if (!isOk) Dispatcher.setForcedAbort(true);
} else if ("unlock".equals(action)) isOk = unlockSemaphore(name);
else exception(infoCells.parts, new Throwable("Bad action: " + action));
View
2  src/fit/WikiRunner.java
@@ -17,7 +17,7 @@ public void process() {
try {
String tags[] = {"wiki", "table", "tr", "td"};
tables = new Parse(input, tags); // look for wiki tag enclosing tables
- fixture.doTables(tables.parts); // only do tables within that tag
+ dispatcher.doTables(tables.parts);
} catch (Exception e) {
exception(e);
}
View
7 src/fit/decorator/CopyAndAppendLastRowTest.java
@@ -37,7 +37,7 @@ public void testSetupDecoratorShouldAddCounterToSummary() throws Exception {
public void testShouldLeaveTableAsItIsIfCounterValueIsZero() throws Exception {
String fitPage = "<table>" + FIRST_HTML_ROW + "<tr><td>fit.decorator.TestFixture</td></tr></table>";
- decorator.doTables(new Parse(fitPage));
+ decorator.doTable(new Parse(fitPage));
TestCaseHelper.assertCounts(TestCaseHelper.counts(0, 0, 0, 0), decorator.counts);
}
@@ -46,7 +46,7 @@ public void testShouldAddOneRowIfCounterValueIsOne() throws Exception {
+ "</td><td>times</td></tr><tr><td>eg.Division</td></tr>"
+ "<tr><td>numerator</td><td>denominator</td><td>quotient()</td></tr>"
+ "<tr><td>10</td><td>2</td><td>5</td></tr></table>";
- decorator.doTables(new Parse(fitPage));
+ decorator.doTable(new Parse(fitPage));
TestCaseHelper.assertCounts(TestCaseHelper.counts(2, 0, 0, 0), decorator.counts);
}
@@ -54,7 +54,7 @@ public void testShouldLeaveTableAsItIsIfTotalRowsAreLessThanThree() throws Excep
String fitPage = "<table><tr><td>" + CopyAndAppendLastRow.class.getName() + "</td>"
+ "<td>0</td><td>times</td></tr><tr><td>eg.Division</td></tr>"
+ "<tr><td>numerator</td><td>denominator</td><td>quotient()</td></tr></table>";
- decorator.doTables(new Parse(fitPage));
+ decorator.doTable(new Parse(fitPage));
TestCaseHelper.assertCounts(TestCaseHelper.counts(0, 0, 0, 0), decorator.counts);
}
@@ -76,5 +76,4 @@ public void testShouldAppendOnlyTheLastRowCounterNumberOfTimes() throws Exceptio
decorator.doTable(new Parse(fitPage));
TestCaseHelper.assertCounts(TestCaseHelper.counts(COUNTER + 3, 0, 0, 0), decorator.counts);
}
-
}
View
47 src/fit/decorator/FixtureDecoratorTestCase.java
@@ -4,6 +4,7 @@
import junit.framework.TestCase;
import fit.Counts;
+import fit.Dispatcher;
import fit.Fixture;
import fit.Parse;
import fit.decorator.exceptions.InvalidInputException;
@@ -25,61 +26,61 @@ public void testShouldBeAbleToExecuteEncapsulatedFixture() throws ParseException
String fitPage = "<table>" + geDecoratorHTMLRow() + "<tr><td>eg.Division</td></tr>"
+ "<tr><td>numerator</td><td>denominator</td><td>quotient()</td></tr>"
+ "<tr><td>100</td><td>4</td><td>25</td></tr></table>";
- Fixture decorator = new Fixture();
- decorator.doTables(new Parse(fitPage));
+ Dispatcher dispatcher = new Dispatcher();
+ dispatcher.doTables(new Parse(fitPage));
int right = 1 + numberOfAssertionsOnDecorator();
- TestCaseHelper.assertCounts(TestCaseHelper.counts(right, 0, 0, 0), decorator.counts);
+ TestCaseHelper.assertCounts(TestCaseHelper.counts(right, 0, 0, 0), dispatcher.counts);
}
public void testShouldBeAbleToFindEncapsulatedFixtureName() throws Exception {
String fitPage = "<table>" + geDecoratorHTMLRow() + "<tr><td>eg.Division</td></tr></table>";
- Fixture decorator = new Fixture();
- decorator.doTables(new Parse(fitPage));
- String encapsulatedFixtureName = (String) decorator.summary.get(FixtureDecorator.ENCAPSULATED_FIXTURE_NAME);
+ Dispatcher dispatcher = new Dispatcher();
+ dispatcher.doTables(new Parse(fitPage));
+ String encapsulatedFixtureName = (String) dispatcher.summary.get(FixtureDecorator.ENCAPSULATED_FIXTURE_NAME);
assertEquals("eg.Division", encapsulatedFixtureName);
}
public void testShouldBeAbleToInstantiateEncapsulatedFixture() throws Exception {
String fitPage = "<table>" + geDecoratorHTMLRow() + "<tr><td>" + TestFixture.class.getName()
+ "</td></tr></table>";
- Fixture decorator = new Fixture();
- decorator.doTables(new Parse(fitPage));
- String encapsulatedFixtureName = (String) decorator.summary.get(FixtureDecorator.ENCAPSULATED_FIXTURE_NAME);
+ Dispatcher dispatcher = new Dispatcher();
+ dispatcher.doTables(new Parse(fitPage));
+ String encapsulatedFixtureName = (String) dispatcher.summary.get(FixtureDecorator.ENCAPSULATED_FIXTURE_NAME);
assertEquals("fit.decorator.TestFixture", encapsulatedFixtureName);
}
public void testShouldDoNothingIfThereIsNoEncapsulatedFixturePresent() throws Exception {
String fitPage = "<table>" + geDecoratorHTMLRow() + "</table>";
- Fixture decorator = new Fixture();
- decorator.doTables(new Parse(fitPage));
- assertNull(decorator.summary.get(FixtureDecorator.ENCAPSULATED_FIXTURE_NAME));
- TestCaseHelper.assertCounts(TestCaseHelper.counts(0, 0, 0, 0), decorator.counts);
+ Dispatcher dispatcher = new Dispatcher();
+ dispatcher.doTables(new Parse(fitPage));
+ assertNull(dispatcher.summary.get(FixtureDecorator.ENCAPSULATED_FIXTURE_NAME));
+ TestCaseHelper.assertCounts(TestCaseHelper.counts(0, 0, 0, 0), dispatcher.counts);
}
public void testShouldMarkExceptionIfEncapsulatingFixtureNameIsInvalid() throws Exception {
String fitPage = "<table>" + geDecoratorHTMLRow() + "<tr><td>invalidClass</td></tr></table>";
- Fixture decorator = new Fixture();
- decorator.doTables(new Parse(fitPage));
- assertEquals(1, decorator.counts.exceptions);
- String encapsulatedFixtureName = (String) decorator.summary.get(FixtureDecorator.ENCAPSULATED_FIXTURE_NAME);
+ Dispatcher dispatcher = new Dispatcher();
+ dispatcher.doTables(new Parse(fitPage));
+ assertEquals(1, dispatcher.counts.exceptions);
+ String encapsulatedFixtureName = (String) dispatcher.summary.get(FixtureDecorator.ENCAPSULATED_FIXTURE_NAME);
assertEquals("invalidClass", encapsulatedFixtureName);
}
public void testShouldStripFirstRowAndPassRestOfTheTableToEncapsulatedFixture() throws Exception {
String fitPage = "<table>" + geDecoratorHTMLRow() + "<tr><td>" + TestFixture.class.getName()
+ "</td></tr></table>";
- Fixture decorator = new Fixture();
- decorator.doTables(new Parse(fitPage));
+ Dispatcher dispatcher = new Dispatcher();
+ dispatcher.doTables(new Parse(fitPage));
String expectedTableContents = "<table><tr><td>" + TestFixture.class.getName() + "</td></tr></table>";
- assertEquals(expectedTableContents, decorator.summary.get(TestFixture.TABLE_CONTENTS));
+ assertEquals(expectedTableContents, dispatcher.summary.get(TestFixture.TABLE_CONTENTS));
}
public void testShouldHandleInvalidInputExceptionIfThrownBySetUpMethod() throws Exception {
String fitPage = "<table>" + geWrongDecoratorHTMLRow() + "<tr><td>" + TestFixture.class.getName()
+ "</td></tr></table>";
- Fixture decorator = new Fixture();
- decorator.doTables(new Parse(fitPage));
- TestCaseHelper.assertCounts(TestCaseHelper.counts(0, 0, 0, 1), decorator.counts);
+ Dispatcher dispatcher = new Dispatcher();
+ dispatcher.doTables(new Parse(fitPage));
+ TestCaseHelper.assertCounts(TestCaseHelper.counts(0, 0, 0, 1), dispatcher.counts);
}
public void testSetAlternativeArgsShouldStoreOddNumberedColumnsToArgsVariable() throws Exception {
View
4 src/fit/testFxtr/HandleFixtureDoesNotExtendFixtureTest.java
@@ -7,7 +7,7 @@
import junit.framework.TestCase;
import util.StringUtil;
-import fit.Fixture;
+import fit.Dispatcher;
import fit.Parse;
public class HandleFixtureDoesNotExtendFixtureTest extends TestCase {
@@ -23,7 +23,7 @@ public void testLearnHowBadFixtureClassIsHandled() throws Exception {
Parse tableForFaultyFixture = new Parse(tableText);
- new Fixture().doTables(tableForFaultyFixture);
+ new Dispatcher().doTables(tableForFaultyFixture);
String fixtureClassCellText = tableForFaultyFixture.at(0, 0, 0).body;
assertEquals("fit.testFxtr.WouldBeFixture<hr/> "
View
15 src/fitnesse/FitFilter.java
@@ -7,6 +7,7 @@
import java.io.InputStreamReader;
import java.io.PrintWriter;
+import fit.Dispatcher;
import fit.Fixture;
import fit.Parse;
@@ -14,7 +15,7 @@
public String input;
public Parse tables;
- public Fixture fixture = new Fixture();
+ public Dispatcher dispatcher = new Dispatcher();
public PrintWriter output;
public static void main(String argv[]) {
@@ -30,9 +31,8 @@ public void run(String argv[]) {
public void process() {
try {
tables = new Parse(input);
- fixture.doTables(tables);
- }
- catch (Exception e) {
+ dispatcher.doTables(tables);
+ } catch (Exception e) {
exception(e);
}
tables.print(output);
@@ -46,8 +46,7 @@ public void args(String[] argv) {
try {
input = read();
output = new PrintWriter(System.out);
- }
- catch (IOException e) {
+ } catch (IOException e) {
System.err.println(e.getMessage());
System.exit(-1);
}
@@ -64,12 +63,12 @@ protected String read() throws IOException {
protected void exception(Exception e) {
tables = new Parse("body", "Unable to parse input. Input ignored.", null, null);
- fixture.exception(tables, e);
+ dispatcher.exception(tables, e);
}
protected void exit() {
output.close();
- System.exit(fixture.counts.wrong + fixture.counts.exceptions);
+ System.exit(dispatcher.counts.wrong + dispatcher.counts.exceptions);
}
}
Something went wrong with that request. Please try again.