diff --git a/.gitignore b/.gitignore index 1589e98..cfef874 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ pom.xml /fitnesse/FitNesseRoot/ErrorLogs /fitnesse/FitNesseRoot/RecentChanges /fitnesse/FitNesseRoot/files/testResults +*.zip diff --git a/fitnesse/FitNesseRoot/FitNesse/SuiteAcceptanceTests/SuiteWidgetTests/TestSubList/content.txt b/fitnesse/FitNesseRoot/FitNesse/SuiteAcceptanceTests/SuiteWidgetTests/TestSubList/content.txt index 6eb00fe..5c6f747 100644 --- a/fitnesse/FitNesseRoot/FitNesse/SuiteAcceptanceTests/SuiteWidgetTests/TestSubList/content.txt +++ b/fitnesse/FitNesseRoot/FitNesse/SuiteAcceptanceTests/SuiteWidgetTests/TestSubList/content.txt @@ -22,16 +22,13 @@ A list created as follows {{{ * Item one # !|Response Examiner.| |type|pattern|matches?|value| -|contents|
  • Item One
  • |true|| +|contents|
  • Item One| diff --git a/fitnesse/FitNesseRoot/FitNesse/UserGuide/QuickReferenceGuide/content.txt b/fitnesse/FitNesseRoot/FitNesse/UserGuide/QuickReferenceGuide/content.txt index ba9c172..bf8aa89 100644 --- a/fitnesse/FitNesseRoot/FitNesse/UserGuide/QuickReferenceGuide/content.txt +++ b/fitnesse/FitNesseRoot/FitNesse/UserGuide/QuickReferenceGuide/content.txt @@ -18,7 +18,9 @@ |!define PageNAME {''!-PageName-!''} |!define PagePATH {''!-PagePath-!''} | |!define LabelNAME {''label-name''} |!define AnyPagePATH {''!-AnyPagePath-!''} | |!define CODE {!--!} |!define CODEend (${FONTend}) | -|!define HDR {!-
    -!}|!define HDRend (${TopOfPAGE}${DIVend}) | + +!define HDR {!-
    -!} +!define HDRend (${TopOfPAGE}${DIVend}) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - !define TOC (|${HDR} Sections ${DIVend}| |!c '''[[ ${FitNESSE} Command Line ][#FitNesseCommandLINE]] ''' | diff --git a/fitnesse/FitNesseRoot/FitNesse/UserGuide/SliM/ScenarioTable/content.txt b/fitnesse/FitNesseRoot/FitNesse/UserGuide/SliM/ScenarioTable/content.txt index ef19bad..4d24993 100644 --- a/fitnesse/FitNesseRoot/FitNesse/UserGuide/SliM/ScenarioTable/content.txt +++ b/fitnesse/FitNesseRoot/FitNesse/UserGuide/SliM/ScenarioTable/content.txt @@ -33,7 +33,8 @@ You can also declare a scenario by embedding underscores within a string. Each |ensure|content matches|@htmlText| |show|content| -The body of the scenario uses the arguments by prefixing them with an '@' sign. The token that follows the '@' ''must be the camel-cased name of the argument.'' +The body of the scenario uses the arguments by prefixing them with an '@' sign. The token that follows the '@' ''must be the camel-cased name of the argument.'' +Arguments that share a common root string can use optional braces to force the correct evaluation of the full name of the argument. Thus, if you have arguments ''job'' and ''job code'', you can use @{jobCode} to make sure you get the argument with the longer name. !4 Invoking a scenario from a DecisionTable !|widget renders| diff --git a/fitnesse/FitNesseRoot/FitNesse/UserGuide/SliM/SlimProtocol/content.txt b/fitnesse/FitNesseRoot/FitNesse/UserGuide/SliM/SlimProtocol/content.txt index f5cd66e..022284f 100644 --- a/fitnesse/FitNesseRoot/FitNesse/UserGuide/SliM/SlimProtocol/content.txt +++ b/fitnesse/FitNesseRoot/FitNesse/UserGuide/SliM/SlimProtocol/content.txt @@ -1,5 +1,5 @@ !2 The Slim Protocol -!note !4 (V0.0) +!note !4 (V0.3) {{{ instruction list +----------+ o---> +------------+ +----------+ +-----+ @@ -29,21 +29,62 @@ That's pretty much it. Lists of instructions go out. Lists of responses come b There is no type information in the instructions. Each instruction is a list of strings. Each response is a list of strings. Strings and lists are the only two types in the entire protocol. It is up to the !-SlimExecutor-! to find the functions and constructors that match the instructions, and to do the necessary type conversion. +!3 The Data +The !-SlimServer-! maintains five pieces of data that are operated on by the instructions that it processes. + * A list of class search path items. + * A dictionary of created objects. Each object is addressed by an instance name string. + * A dictionary of symbol values. Each symbol value is addressed by a symbol name string. + * ''[0.1]'' '''Library Instances:''' A stack of library objects. + * ''[0.3]'' '''Actors:''' A stack of actor objects. + !3 The Instructions There are four instructions in the Slim protocol. import, make, call, and callAndAssign. That's all. - * Import: ['''', ''import'', ''''] This instruction causes the to be added to the search path for fixtures. In java gets added to the ''CLASSPATH''. In ''.NET'', the would name a dll. You can send as many imports as you like. The Slim system will use all imported paths to find fixture classes. This instruction returns ''OK''. - * Make: ['''', ''make'', '''', '''', ''...''] This instruction causes slim to search for a class named '''' in the imported search paths. '''' can also be fully qualified. If found slim looks for a constructor with the right number of arguments. If found, the '''' strings are converted to the appropriate types, and the constructor is called. The newly created instance is registered under the name '''', and the instruction returns ''OK''. The '''' may contain symbols (see below). +!4 Import +['''', import, ''''] + +This instruction causes the to be added to the list of class search path items. In java gets added to the ''CLASSPATH''. In ''.NET'', the is a namespace. You can send as many imports as you like. The Slim system will use all imported paths to find fixture classes. This instruction returns ''OK''. + +!4 Make +['''', make, '''', '''', ''...''] + +This instruction causes slim to search for a class named '''' using the list of class search path items. '''' can also be fully qualified. If found slim looks for a constructor with the right number of arguments. If found, the '''' strings are converted to the appropriate types, and the constructor is called. The newly created instance is added to the dictionary of created objects with the name '''', and the instruction returns ''OK''. + +''[0.1]'' '''Library Instances:''' If a ''make'' instruction creates an object with an instance name that begins with !style_code(library) then that instance is pushed on the stack of library objects. These objects endure for the entire duration of the !-SlimServer-! execution. + +''[0.2]'' '''Fixture Chaining:''' Symbols can be used in the ''Make'' command to represent a class name. If the '''' argument of the ''Make'' command contains '$' characters, then Slim should replace any symbols that have been created by previous ''callAndAssign'' commands. This allows !-FitNesse-! to compose fixture names from symbols set by fixtures, and therefore enables fixture chaining. + +''[0.3]'' '''Symbol Copy:''' If '''' consists entirely of a single symbol name prefixed with $, then the item from the dictionary of symbol values with the symbol name is added to the dictionary of created objects with the name ''''. The '''' strings are ignored and no constructor is called. - * Call: ['''',''call'','''','''',''...''] This instruction causes slim to find a function named '''' in the class of the object registered under ''''. The function must have the same number of arguments as the instruction. If found, each argument in the instruction is converted to the appropriate type, and then the function is called on the instance. If the function returns a value, it is converted to a string and returned. Otherwise the instruction returns the string: ''/__VOID__/''. +!4 Call +['''', call,'''','''',''...''] - * !-CallAndAssign-!: ['''', ''callAndAssign'', '''', '''', '''', ''...''] This instruction is identical to ''call'' except that the return value is saved in a symbol named ''''. That symbol is kept in a dictionary in the SLIM system. Symbol names may only contain letters. +This instruction causes slim to find a function named '''' in the class of the object from the dictionary of created objects with the name ''''. The function must have the same number of arguments as the instruction. If found, each argument in the instruction is converted to the appropriate type, and then the function is called on the instance. The '''' strings may contain symbols (see below) which will be substituted before the type conversion is done. If the function returns a value, it is converted to a string and returned. Otherwise the instruction returns the string: ''/__VOID__/''. -!4 Symbols +''[0.1]'' '''System Under Test:''' Each fixture may have a way to declare a particular object to be the ''System Under Test''. In java this is done with the @SystemUnderTest attribute. In !-RubySlim-! the object is accessed using the ''sut'' method. In .NET, the fixture implements the !-DomainAdapter-! interface. Whatever mechanism is used, if a the method specified by a ''Call'' or ''!-CallAndAssign-!'' is not found on the specified instance, then if there is a ''System Under Test'' object specified, and the method exists on that object, then it will be called. + +''[0.1]'' '''Library Instances:''' If a method specified by a ''Call'' or ''!-CallAndAssign-!'' is not found on either the specified instance, or on the ''System Under Test'' then the stack of library objects is searched, starting at the top (latest). If the method is found, it is called. + +''[0.3]'' '''Symbol As Object:''' If an '''' consists entirely of a single symbol name prefixed with $, then the item from the dictionary of symbol values with the symbol name is used directly as an argument in the function call. + +!4 !-CallAndAssign-! +['''', callAndAssign, '''', '''', '''', ''...''] + +This instruction is identical to ''call'' except that the return value is saved in the dictionary of symbol values with the name ''''. Symbol names may only contain letters. + +!3 Symbols That last one was probably puzzling. Symbol values are strings or objects (or null values) that are kept in a dictionary. The ''callAndAssign'' instruction is the only thing that can create a symbol. Symbols are used in in the '''' strings of the ''make'', ''call'', and ''callAndAssign'' instructions. If one of those '''' strings contains a $ followed by a symbol name (as in $V), and if the symbol has been assigned, then that string will be replaced by the value of the symbol. What this means is that the !-FitNesse-! side can tell Slim to remember a value in a symbol, and then to use that value later. -If the symbol is replaced within a string context, it will be converted to a string. If only the $ followed by a symbol name is given and an object is stored for that symbol, then the object will be used. A symbol may also be used in the '''' string of the ''make'' instruction. If the symbol evaluates to an object, then this object instance is registered under the name '''' and the ''...'' part is ignored in this case. -!4 Strings and Lists +''[0.3]'' '''Symbol As Object:''' If the symbol is replaced within a string context, it will be converted to a string. If only the $ followed by a symbol name is given and an object is stored for that symbol, then the object will be used. + +!3 Actors + +''[0.3]'' The stack of library objects should be initialized with an instance of a class with the following 3 methods: + * getFixture(): returns the object from the dictionary of created objects named "scriptTableActor". Throws an exception if no object exists. + * pushFixture(): pushes the object from the dictionary of created objects named "scriptTableActor" on to the stack of actor objects. Throws an exception if no object exists. + * popFixture(): pops an object from the stack of actor objects and adds it to the dictionary of created objects with the name "scriptTableActor". Throws an exception if the stack is empty. + +!3 Strings and Lists As we will see, slim views a list as a special kind of string. Therefore functions can take and return lists as well as strings. The lists must be lists of strings, but since a list is a special kind of string, lists of lists of lists of ... are possible. The Slim executor will convert back and forth between these forms as needed. A string is encoded as six digits followed by a colon, followed by the characters of the string. The six digits are the number of characters in the string, not including the digits themselves. Thus, the empty string is "000000:". This length encoding scheme is used in other places so we'll use the token '''' to mean six digits followed by a colon. @@ -56,7 +97,7 @@ As you can see, each item of a list is a string. But since a string can encode !5 !note You might think that 6 digits is plenty; but the last few decades have shown us that a megabyte isn't even close to infinite. So you'll want to keep that in mind. -!4 Slim Server. +!3 Slim Server. So when you send a list of instructions, what you are really sending is a string. When you receive a list of responses, what you are really receiving is a string. So the high level protocol of Slim is just strings. It looks like this: 1 !-FitNesse-! invokes the Slim Server via a command line. One of the command line arguments is the port number of the socket to listen on. !-FitNesse-! opens that socket. @@ -66,9 +107,9 @@ So when you send a list of instructions, what you are really sending is a string 5 3 and 4 repeat until !-FitNesse-! sends a ''bye'' directive. This is simply the string ''bye'' properly encoded with ''''. e.g. "000003:bye". 6 Slim Server shuts down. -!4 Exceptions +!3 Exceptions Sometimes a function or a constructor will throw an exception in response to a ''make'', ''call'', or ''callAndAssign'' instruction. When this happens, the response value for that instruction will be: "__EXCEPTION__:''''". The '''' ought to be a stack trace or some other relevant debugging information. If you want a nice yellow message to appear in one of the SLIM tables, then somewhere in the ''<>'' put ''message:<<'' in front of the message and ''>>'' after it. e.g. !style_code(message:<>) -!5 Standard exception messages +!4 Standard exception messages There are some standard exception messages that every Slim implementation should create. |COULD_NOT_INVOKE_CONSTRUCTOR ''''|Where '''' is the name of the class whose constructor cannot be invoked.| @@ -82,44 +123,12 @@ There are some standard exception messages that every Slim implementation should !4 Aborting a Test If a fixture throws an exception with a ''class'' name that contains "!style_code(!-StopTest-!)", then Slim should stop executing the instructions in the current batch, and return immediately. The response for this type of exception should be "!style_code(__EXCEPTION__:ABORT_SLIM_TEST:)" which may have an optional suffix of: "!style_code(message:<<''reason''>>)". - -!4 Type Conversions +!3 Type Conversions The only types in the instructions and responses are lists and strings, and since the leaves of the lists must eventually be strings, all we really have to worry about are strings. But we don't want to restrict our fixtures to use only Strings. So Slim comes with some standard type converters that allow fixtures to take more convenient data types. !see DataTypes. -!4 Conclusion -That's pretty much it. If you want to port Slim to a new platform, I suggest you look at the code in the fitnesse.slim package. Pay special attention to the !-ListSerializer-! and !-ListDeserializer-! classes. Also check out the logic in Statement and !-StatementExecutor-! classes. The unit tests ought to be expecially educational. You should be able to build equivalent unit tests without much fuss. Finally, take a look at the unit tests in fitnesse.responders.run.slimResponder. These should all still run with your new port (although you'll have to replace the command line that invokes the Slim Server). - ------- -!2 Slim Protocol (V0.1) -!4 System Under Test -Each fixture may have a way to declare a particular object to be the ''System Under Test''. In java this is done with the @SystemUnderTest attribute. In RubySlim the object is accessed using the ''sut'' method. Whatever mechanism is used, if a the method specified by a ''Call'' or ''!-CallAndAssign-!'' is not found on the specified instance, then if there is a ''System Under Test'' object specified, and the method exists on that object, then it will be called. - -!4 Library Instances -If a ''make'' instruction creates an object with an instance name that begins with !style_code(library) then that instance is pushed on the top of a stack of special library instances. These instances endure for the entire duration of the SlimServer execution. If a method specified by a ''Call'' or ''!-CallAndAssign-!'' is not found on either the specified instance, or on the ''System Under Test'' then the stack of ''library'' instances is searched, starting at the top (latest). If the method is found, it is called. +''[0.1]'' '''Hashes:''' !style_note(Optional) If one of the method arguments int a ''Make'', ''Call'', or ''!-CallAndAssign-!'' matches the "hash" format, then it should be converted into a dictionary, or a hash, or some convenient form for the fixture authors. In Java they are converted into Maps. In Ruby they are converted into Hashes. Other languages may use other structures. The "hash" format is the format produced by the [[Hash Widget][namevalue...). -!4 Hashes !style_note(Optional) -If one of the method arguments int a ''Make'', ''Call'', or ''!-CallAndAssign-!'' matches the "hash" format, then it should be converted into a dictionary, or a hash, or some convenient form for the fixture authors. In Java they are converted into Maps. In Ruby they are converted into Hashes. Other languages may use other structures. The "hash" format is the format produced by the [[Hash Widget][namevalue...). - ------- -!2 Slim Protocol (V0.2) -!4 Fixture Chaining. -Symbols can be used in the ''Make'' command to respresent a class name. If the '''' argument of the ''Make'' command contains '$' characters, then Slim should replace any symbols that have been created by previous ''callAndAssign'' commands. This allows !-FitNesse-! to compose fixture names from symbols set by fixtures, and therefore enables fixture chaining. - -!see map conversion -* smarter function lookup - default to the same namespace as the fixture -generator -* get the rest of the Slim acceptance tests passing -* unit test coverage for statement-executor ns - -## License - -Copyright (C) 2011 Colin Jones - -Distributed under the MIT License. diff --git a/fitnesse/clojureslim/bin/clojureslim b/fitnesse/clojureslim/bin/clojureslim deleted file mode 100644 index 0c7467a..0000000 --- a/fitnesse/clojureslim/bin/clojureslim +++ /dev/null @@ -1 +0,0 @@ -java -cp dist/fitnesse.jar:clojureslim/lib/clojure-1.2.1.jar:clojureslim/src clojure.main clojureslim/script/clojureslim.clj 8081 diff --git a/fitnesse/clojureslim/examples/clojureslim/fixtures.clj b/fitnesse/clojureslim/examples/clojureslim/fixtures.clj deleted file mode 100644 index 12e2abe..0000000 --- a/fitnesse/clojureslim/examples/clojureslim/fixtures.clj +++ /dev/null @@ -1,201 +0,0 @@ -(ns clojureslim.fixtures - (:require [clojureslim.statement-executor :as se]) - (:import [java.io Writer] - [fitnesse.fixtures SplitFixture - DuplicateRows])) - -(defrecord TestSlim [constructor-arg state] - Object - (toString [this] - (if constructor-arg - (str "TestSlim: " constructor-arg ", " (:string @state)) - (str "TestSlim: null, " @state)))) - -(defn make-fixture - ([] (make-fixture nil)) - ([constructor-arg] - (TestSlim. constructor-arg (atom {}))) - ([constructor-arg base-fixture] - (TestSlim. constructor-arg (atom @(:state base-fixture))))) - -(defn echo [this thing-to-echo] - thing-to-echo) - -(defn echo-fixture [] - (make-fixture)) - -(defn echo-string [this s] - s) - -(defn echo-int [this i] - i) - -(defn test-slim - ([] - (make-fixture 0)) - ([& args] - (apply make-fixture args))) - -(defn echo-boolean [this arg] - (boolean arg)) - - - -(defn should-i-buy-milk [] - (make-fixture)) - -(defn set-cash-in-wallet [this x] - (swap! this assoc :cash-in-wallet (Integer/parseInt x))) - -(defn set-credit-card [this x] - (swap! this assoc :credit-card (= "yes" x))) - -(defn set-pints-of-milk-remaining [this x] - (swap! this assoc :pints-of-milk-remaining (Integer/parseInt x))) - -(defn go-to-store [this] - (let [state @this] - (if (and (= 0 (:pints-of-milk-remaining state)) - (or (< 2 (:cash-in-wallet state)) - (:credit-card state))) - "yes" - "no"))) - - - -(defn some-decision-table [] - (atom {})) - -;(defmulti set-input [this in] #(type %2)) -(defn set-input [this in] - (swap! this assoc :input (Integer/parseInt in))) - -(defn set-string [this in] - (swap! (:state this) assoc :string in)) - -(defn get-string-arg [this] - (:string @(:state this))) - -(defn is-same [this other] - (= this other)) - -(defn get-string-from-other [this other] - (get-string-arg other)) - -(defn return-constructor-arg [this] - (:constructor-arg this)) - -(defn output [this] - (let [in (:input @this)] - (* in 2))) - -(defprotocol QueryTable - (query [this])) - -; whole table -; first [and only] row -; first column (label-value) -; second column (label-value) -(defrecord TestQuery [args] - QueryTable - (query [this] - [[["n" 1] - ["2n" 2]]])) - -(defn test-query [& args] - (TestQuery. args)) - - -(defn create-test-slim-with-string [this s] - (let [fixture (make-fixture)] - (set-string fixture s) - fixture)) - - -; TODO: this may actually need to be in the library proper -(def actor-instance-name "scriptTableActor") -(def fixture-stack (atom [])) - -(defn get-fixture [this] - (let [executor (se/make-statement-executor)] - (.getInstance executor actor-instance-name))) - -(defn push-fixture [this] - (swap! fixture-stack conj (get-fixture this))) - -(defn pop-fixture [this] - (let [popped (last @fixture-stack)] - (swap! fixture-stack pop) - (se/set-instance actor-instance-name popped))) - -(defn uncle [] - (make-fixture)) - - -; TODO: extract? -(extend-type SplitFixture - QueryTable - (query [this] - (.query this))) - -(defn split-fixture [string-to-split] - (SplitFixture. string-to-split)) - -(defn null-fixture - ([] (make-fixture)) - ([s] (make-fixture))) - -(defn get-null [this] - nil) - -(defn get-blank [this] - "") - -(defrecord MySystemUnderTestDriver [system-under-test called]) - -(defn make-system-under-test [] - {:called (atom false)}) - -(defn foo [this] - (swap! (:called this) not)) -(def bar - (comp foo :system-under-test)) - -(defn driver-called [this] - @(:called this)) -(defn system-under-test-called [this] - @(:called (:system-under-test this))) - - -(defn my-system-under-test-driver [] - (MySystemUnderTestDriver. (make-system-under-test) - (atom false))) - -(defn dummy-table-table-returns-null [] - (make-fixture)) -(defn do-table [this args] - ) - -(extend-type DuplicateRows - QueryTable - (query [this] - (.query this))) - -(defn duplicate-rows [arg] - (DuplicateRows. arg)) - -; TODO: avoid the need to do things like this by ordering the search path -(defn set-the-name [this s] - (swap! (:state this) assoc :the-name s)) -(defn the-name [this] - (:the-name @(:state this))) - - -(defn concatenate-three-args [this a b c] - (str a " " b " " c)) - -(defn login-dialog-driver [username password] - (make-fixture [username password])) - -(defn login-with-username-and-password [this username password] - (= (:constructor-arg this) [username password])) diff --git a/fitnesse/clojureslim/examples/me.clj b/fitnesse/clojureslim/examples/me.clj deleted file mode 100644 index 69d7dab..0000000 --- a/fitnesse/clojureslim/examples/me.clj +++ /dev/null @@ -1 +0,0 @@ -(ns me) diff --git a/fitnesse/clojureslim/project.clj b/fitnesse/clojureslim/project.clj deleted file mode 100644 index 4311ada..0000000 --- a/fitnesse/clojureslim/project.clj +++ /dev/null @@ -1,7 +0,0 @@ -(defproject clojureslim "0.0.1-SNAPSHOT" - :description "The Slim (Simple List Invocation Method) protocol implented for Clojure" - :dependencies [[org.clojure/clojure "1.2.1"]] - :dev-dependencies [[speclj "1.4.0"] - [org.clojars.trptcolin/fitnesse "20110721"]] - :dev-resources-path "examples" - :test-path "spec") diff --git a/fitnesse/clojureslim/sample_fitnesse_test.txt b/fitnesse/clojureslim/sample_fitnesse_test.txt deleted file mode 100644 index 551b123..0000000 --- a/fitnesse/clojureslim/sample_fitnesse_test.txt +++ /dev/null @@ -1,53 +0,0 @@ -# Steps to in-development success - -* `lein deps` -* `ln -s /path/to/clojureslim /path/to/fitnesse` - * as peer to FitnesseRoot - -# Example tests - -!define TEST_SYSTEM {slim} -!define TEST_RUNNER {clojure.main clojureslim/script/clojureslim.clj} -!define COMMAND_PATTERN {java -cp %p %m} -!define PATH_SEPARATOR {:} - -!path dist/fitnesse.jar -!path clojureslim/lib/clojure-1.2.1.jar -!path clojureslim/src -!path clojureslim/examples - -!|import| -|clojureslim.clj-test| - -!|script|clj-test-first| -| check | something happened | false | -| run | -| check | something happened | true | - - -!|script|echo fixture| -|$TEST_SLIM=|echo|TestSlim| - -!|script|$TEST_SLIM| -|ensure|echo boolean|true| - - - -|should I buy milk| -|cash in wallet|credit card|pints of milk remaining|go to store?| -| 0 | no | 0 | no | -| 10 | no | 0 | yes | -| 0 | yes | 0 | yes | -| 10 | yes | 0 | yes | -| 0 | no | 1 | no | -| 10 | no | 1 | no | -| 0 | yes | 1 | no | -| 10 | yes | 1 | no | - -|some decision table| -|input| output?| -| 3 | $V= | -| $V | 12 | -| 10 | $V= | -| $V | 40 | - diff --git a/fitnesse/clojureslim/script/clojureslim.clj b/fitnesse/clojureslim/script/clojureslim.clj deleted file mode 100644 index 248c678..0000000 --- a/fitnesse/clojureslim/script/clojureslim.clj +++ /dev/null @@ -1,3 +0,0 @@ -(require 'clojureslim) - -(apply clojureslim/main *command-line-args*) diff --git a/fitnesse/clojureslim/spec/clojureslim/statement_executor_spec.clj b/fitnesse/clojureslim/spec/clojureslim/statement_executor_spec.clj deleted file mode 100644 index 1232a6a..0000000 --- a/fitnesse/clojureslim/spec/clojureslim/statement_executor_spec.clj +++ /dev/null @@ -1,9 +0,0 @@ -(ns clojureslim.statement-executor-spec - (:use [speclj.core] - [clojureslim.statement-executor]) - ) - -(describe "statement-executor" - (it "should be" - (should (make-statement-executor))) - ) diff --git a/fitnesse/clojureslim/spec/clojureslim/text_transformations_spec.clj b/fitnesse/clojureslim/spec/clojureslim/text_transformations_spec.clj deleted file mode 100644 index 20d04c1..0000000 --- a/fitnesse/clojureslim/spec/clojureslim/text_transformations_spec.clj +++ /dev/null @@ -1,23 +0,0 @@ -(ns clojureslim.text-transformations-spec - (:use [speclj.core] - [clojureslim.text-transformations])) - -(describe "dasherize" - - (it "leaves simple cases alone" - (should= "foo" (dasherize "foo"))) - - (it "downcases a single word" - (should= "foo" (dasherize "Foo"))) - - (it "splits camel cases with a dash" - (should= "foo-bar" (dasherize "FooBar"))) - - (it "leaves already-dashed cases alone" - (should= "foo-bar" (dasherize "foo-bar"))) - - (it "converts snake case" - (should= "foo-bar" (dasherize "foo_bar")))) - - - diff --git a/fitnesse/clojureslim/spec/clojureslim/variables_spec.clj b/fitnesse/clojureslim/spec/clojureslim/variables_spec.clj deleted file mode 100644 index 03dcc32..0000000 --- a/fitnesse/clojureslim/spec/clojureslim/variables_spec.clj +++ /dev/null @@ -1,41 +0,0 @@ -(ns clojureslim.variables-spec - (:use [clojureslim.variables] - [speclj.core])) - -(describe "replace-slim-variables-in-string" - - (it "gives the argument back by default" - (should= "foo" (replace-slim-variables-in-string {} "foo"))) - - (it "replaces in the simplest case" - (should= "something" - (replace-slim-variables-in-string - {"THEKEY" "something"} - "$THEKEY"))) - - (it "replaces when the variable is in the middle" - (should= "query-something" - (replace-slim-variables-in-string - {"THEKEY" "something"} - "query-$THEKEY"))) - - (it "replaces multiple variables" - (should= "bar-query-something" - (replace-slim-variables-in-string - {"THEKEY" "something" - "FOO" "bar"} - "$FOO-query-$THEKEY"))) - - (it "allows similarly-named variables" - (should= "foo-bar-baz" - (replace-slim-variables-in-string - {"VALUE" "bar" - "VALUEX" "baz"} - "foo-$VALUE-$VALUEX"))) - - (it "replaces with non-string variable values" - (let [container (atom {})] - (should= container - (replace-slim-variables-in-string - {"FOO" container} - "$FOO"))))) diff --git a/fitnesse/clojureslim/src/clojureslim.clj b/fitnesse/clojureslim/src/clojureslim.clj deleted file mode 100644 index 87eee36..0000000 --- a/fitnesse/clojureslim/src/clojureslim.clj +++ /dev/null @@ -1,31 +0,0 @@ -(ns clojureslim - (:require [clojureslim.statement-executor :as statement-executor] - [clojureslim.text-transformations :as tt]) - (:import [fitnesse.slim JavaSlimFactory - NameTranslator - SlimFactory - SlimServer - SlimService])) - -(defn make-method-name-translator [] - (proxy [NameTranslator] [] - (translate [s] (tt/dasherize s)))) - -(defn make-clojure-slim-factory [method-name-translator statement-executor] - (proxy [SlimFactory] [] - (getMethodNameTranslator [] - method-name-translator) - (getStatementExecutor [] - statement-executor))) - -(defn main [& args] - (let [port (Integer/parseInt (first args)) - method-name-translator (make-method-name-translator) - statement-executor (statement-executor/make-statement-executor) - slim-factory (make-clojure-slim-factory - method-name-translator - statement-executor) - verbose true - slim-server (.getSlimServer slim-factory verbose)] - (SlimService. port slim-server))) - diff --git a/fitnesse/clojureslim/src/clojureslim/statement_executor.clj b/fitnesse/clojureslim/src/clojureslim/statement_executor.clj deleted file mode 100644 index 9f02fbe..0000000 --- a/fitnesse/clojureslim/src/clojureslim/statement_executor.clj +++ /dev/null @@ -1,134 +0,0 @@ -(ns clojureslim.statement-executor - (:require [clojureslim.text-transformations :as tt] - [clojureslim.variables :as variables] - [clojure.string :as string]) - (:import [fitnesse.slim StatementExecutor])) - -(def instances (atom {})) -(defn set-instance [instance-name value] - (swap! instances assoc instance-name value)) - -(def slim-variables (atom {})) - -(def exception-tag "__EXCEPTION__:") - -(defn assign-slim-variable [variable value] - (swap! slim-variables assoc variable value)) - -(defn replace-slim-variables [args] - (variables/replace-slim-variables @slim-variables args)) - -(defn find-function - ([name] - (last ; the var itself - (first ; TODO: handle collisions - (filter (fn [[k v]] (= k (symbol name))) - (mapcat ns-publics (all-ns)))))) - ; TODO: pick smartly - same ns as the constructor - ([name instance] - (find-function name))) - -(def unreported-exception-function-names - #{"table" "begin-table" "end-table" "reset" "execute"}) - -(defn make-statement-executor [] - (proxy [StatementExecutor] [] - - ; public abstract void setVariable(String name, Object value); - ; TODO: postponing for now because its only effects are changing behavior of other methods - (setVariable [name value] - (println "setVariable called")) - - (addPath [path] - (try - (require (symbol path)) - "OK" - (catch Exception e - (str exception-tag " " e)))) - - (create [instance-name fixture-name args] - (try - (let [fixture-name-or-instance (first (replace-slim-variables [fixture-name])) - args (replace-slim-variables args)] - (cond (not (string? fixture-name-or-instance)) - (do (swap! instances assoc instance-name fixture-name-or-instance) - "OK") - (re-seq #"^library" instance-name) - ; include library globally - (do - (.addPath this fixture-name)) - ; call-function - (re-seq #"/" fixture-name) - (let [[fixture-ns fixture-fn] (string/split fixture-name #"/")] - (prn fixture-ns fixture-fn) - (apply - (ns-resolve (symbol fixture-ns) (symbol fixture-fn)) - args)) - :default - (let [replaced-fixture-name (tt/dasherize fixture-name-or-instance) - _ (prn replaced-fixture-name)] - (if-let [fixture-generator (find-function replaced-fixture-name)] - (let [instance (apply fixture-generator args)] - (swap! instances assoc instance-name instance) - "OK") - (do - (print-str - exception-tag - (format "message:<>" - replaced-fixture-name - (count args)))))))) - (catch Throwable e - (print-str exception-tag - "Problem creating fixture for" fixture-name - "\n" (tt/pr-str-stack-trace e))))) - - ; public abstract Object getInstance(String instanceName); - ; TODO: implement. who calls this anyway? - (getInstance [instance-name] - (println "getInstance called: " instance-name) - (let [instance (get @instances instance-name)] - (prn instance) - instance)) - - ; TODO: make this smarter - use same ns as the instance - (call [instance-name method-name args] - (let [replaced-args (replace-slim-variables args)] - (try - (let [instance (@instances instance-name) - method (find-function method-name instance)] - (apply method instance replaced-args)) - (catch Throwable e - (if (unreported-exception-function-names method-name) - nil - (print-str exception-tag - (format "message:<>" - method-name - (count args) - instance-name) - (pr-str (first replaced-args)) - (tt/pr-str-stack-trace e))))))) - - ; public abstract boolean stopHasBeenRequested(); - ; TODO: this definitely won't do in the long run - (stopHasBeenRequested [] - false) - - ; public abstract void reset(); - ; TODO: implement - (reset [] - (println "reset called")) - - ; public abstract Object callAndAssign(String variable, String instanceName, String methodName, - ; Object[] args); - ; store slim variables - ; TODO: store these - ; TODO: replace method calls with the values that are stored - (callAndAssign [variable instance-name method-name args] - (println "callAndAssign called with variable" variable - ", instance-name" instance-name - ", method-name" method-name - ", args" (seq args)) - (let [result (.call this instance-name method-name args)] - (assign-slim-variable variable result) - result)))) - diff --git a/fitnesse/clojureslim/src/clojureslim/text_transformations.clj b/fitnesse/clojureslim/src/clojureslim/text_transformations.clj deleted file mode 100644 index cc0a692..0000000 --- a/fitnesse/clojureslim/src/clojureslim/text_transformations.clj +++ /dev/null @@ -1,17 +0,0 @@ -(ns clojureslim.text-transformations - (:require [clojure.string :as string])) - -(defn dasherize - "Converts the given string from camel case to a more idiomatic-Clojure dashed - style." - [s] - (string/join - "-" - (let [parts (drop-while string/blank? - (.split s "(?=[^a-z])")) - lowercase-parts (map string/lower-case parts)] - (map #(string/replace % #"[^a-zA-Z]+" "") lowercase-parts)))) - -(defn pr-str-stack-trace [e] - (string/join "\n" (cons e (.getStackTrace e)))) - diff --git a/fitnesse/clojureslim/src/clojureslim/variables.clj b/fitnesse/clojureslim/src/clojureslim/variables.clj deleted file mode 100644 index 218f877..0000000 --- a/fitnesse/clojureslim/src/clojureslim/variables.clj +++ /dev/null @@ -1,37 +0,0 @@ -(ns clojureslim.variables - (:require [clojure.string :as string])) - -(defn- get-slim-variable-value [slim-variables word] - (get slim-variables - (string/replace word #"\$" "") - word)) - -(defmulti replace-slim-variables-in - "Finds Slim variables in the given object from the given map of variables, - designated by $ followed by any word characters (\\w in a regex sense, just - like [a-zA-Z_]), and attempts to replace them from the map. Falls back to - leaving the variable name in place." - (comp type second vector)) - -; TODO: do we ever have a weird case of multiple non-string values? -(defmethod replace-slim-variables-in - String - [slim-variables initial-string] - (let [variable-attempts (reverse (sort-by count - (re-seq #"\$[^$\W]*" initial-string))) - replacements (map (partial get-slim-variable-value slim-variables) - variable-attempts)] - (if (every? string? replacements) - (reduce - #(string/replace %1 %2 (get-slim-variable-value slim-variables %2)) - initial-string - variable-attempts) - (first replacements)))) - -(defmethod replace-slim-variables-in - :default - [slim-variables initial-object] - initial-object) - -(defn replace-slim-variables [slim-variables args] - (map (partial replace-slim-variables-in slim-variables) args)) diff --git a/fitnesse/fitnesse.jar b/fitnesse/fitnesse.jar index 5c3f81d..07775d9 100644 Binary files a/fitnesse/fitnesse.jar and b/fitnesse/fitnesse.jar differ diff --git a/project.clj b/project.clj index 46d731c..e549c9c 100644 --- a/project.clj +++ b/project.clj @@ -2,5 +2,6 @@ :description "FIXME: write description" :dependencies [[org.clojure/clojure "1.2.1"] [joodo "0.6.0-SNAPSHOT"]] - :dev-dependencies [[speclj "1.4.0"]] + :dev-dependencies [[speclj "1.4.0"] + [clojureslim "0.0.1-SNAPSHOT"]] :test-path "spec")