rubyslim-unofficial 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/.gitignore +7 -0
  2. data/Gemfile +2 -0
  3. data/README.md +187 -0
  4. data/Rakefile +21 -0
  5. data/bin/rubyslim +10 -0
  6. data/lib/rubyslim/list_deserializer.rb +69 -0
  7. data/lib/rubyslim/list_executor.rb +12 -0
  8. data/lib/rubyslim/list_serializer.rb +45 -0
  9. data/lib/rubyslim/ruby_slim.rb +61 -0
  10. data/lib/rubyslim/slim_error.rb +3 -0
  11. data/lib/rubyslim/slim_helper_library.rb +23 -0
  12. data/lib/rubyslim/socket_service.rb +53 -0
  13. data/lib/rubyslim/statement.rb +79 -0
  14. data/lib/rubyslim/statement_executor.rb +174 -0
  15. data/lib/rubyslim/table_to_hash_converter.rb +32 -0
  16. data/lib/test_module/library_new.rb +13 -0
  17. data/lib/test_module/library_old.rb +12 -0
  18. data/lib/test_module/should_not_find_test_slim_in_here/test_slim.rb +7 -0
  19. data/lib/test_module/simple_script.rb +9 -0
  20. data/lib/test_module/test_chain.rb +5 -0
  21. data/lib/test_module/test_slim.rb +86 -0
  22. data/lib/test_module/test_slim_with_arguments.rb +23 -0
  23. data/lib/test_module/test_slim_with_no_sut.rb +5 -0
  24. data/rubyslim-unofficial.gemspec +25 -0
  25. data/spec/instance_creation_spec.rb +40 -0
  26. data/spec/it8f_spec.rb +8 -0
  27. data/spec/list_deserializer_spec.rb +66 -0
  28. data/spec/list_executor_spec.rb +187 -0
  29. data/spec/list_serialzer_spec.rb +38 -0
  30. data/spec/method_invocation_spec.rb +127 -0
  31. data/spec/slim_helper_library_spec.rb +80 -0
  32. data/spec/socket_service_spec.rb +98 -0
  33. data/spec/spec_helper.rb +6 -0
  34. data/spec/statement_executor_spec.rb +50 -0
  35. data/spec/statement_spec.rb +17 -0
  36. data/spec/table_to_hash_converter_spec.rb +31 -0
  37. metadata +132 -0
@@ -0,0 +1,174 @@
1
+ require "rubyslim/slim_error"
2
+ require "rubyslim/statement"
3
+ require "rubyslim/table_to_hash_converter"
4
+ require "rubyslim/slim_helper_library"
5
+
6
+ class StatementExecutor
7
+ def initialize
8
+ @instances = {}
9
+ @modules = []
10
+ @symbols = {}
11
+ @libraries = [SlimHelperLibrary.new(self)]
12
+ end
13
+
14
+ def library?(instance_name)
15
+ library_prefix = "library"
16
+ instance_name[0, library_prefix.length] == library_prefix
17
+ end
18
+
19
+ def create(instance_name, class_name, constructor_arguments)
20
+ begin
21
+ instance = replace_symbol(class_name)
22
+ if instance.is_a?(String)
23
+ instance = construct_instance(instance, replace_symbols(constructor_arguments))
24
+ if library?(instance_name)
25
+ @libraries << instance
26
+ end
27
+ end
28
+ set_instance(instance_name, instance)
29
+ "OK"
30
+ rescue SlimError => e
31
+ Statement::EXCEPTION_TAG + e.to_s
32
+ end
33
+ end
34
+
35
+ def set_instance(instance_name, instance)
36
+ @instances[instance_name] = instance
37
+ end
38
+
39
+ def construct_instance(class_name, constructor_arguments)
40
+ require_class(class_name);
41
+ construct(class_name, constructor_arguments);
42
+ end
43
+
44
+
45
+ def make_path_to_class(class_name)
46
+ module_names = split_class_name(class_name)
47
+ files = module_names.collect { |module_name| to_file_name(module_name) }
48
+ File.join(files)
49
+ end
50
+
51
+ def split_class_name(class_name)
52
+ class_name.split(/\:\:/)
53
+ end
54
+
55
+ def replace_tables_with_hashes(constructor_arguments)
56
+ args = constructor_arguments.map do |arg|
57
+ TableToHashConverter.convert arg
58
+ end
59
+ return args
60
+ end
61
+
62
+ def construct(class_name, constructor_arguments)
63
+ class_object = get_class(class_name)
64
+ begin
65
+ class_object.new(*replace_tables_with_hashes(constructor_arguments))
66
+ rescue ArgumentError => e
67
+ raise SlimError.new("message:<<COULD_NOT_INVOKE_CONSTRUCTOR #{class_name}[#{constructor_arguments.length}]>>")
68
+ end
69
+ end
70
+
71
+
72
+ def with_each_fully_qualified_class_name(class_name, &block)
73
+ (@modules.map { |module_name| module_name + "::" + class_name } << class_name).reverse.each &block
74
+ end
75
+
76
+ def require_class(class_name)
77
+ with_each_fully_qualified_class_name(class_name) do |fully_qualified_name|
78
+ begin
79
+ require make_path_to_class(fully_qualified_name)
80
+ return
81
+ rescue LoadError
82
+ end
83
+ end
84
+ raise SlimError.new("message:<<COULD_NOT_INVOKE_CONSTRUCTOR #{class_name} failed to find in #{@modules.map { |mod| make_path_to_class(mod) }.inspect}>>")
85
+ end
86
+
87
+ def get_class(class_name)
88
+ with_each_fully_qualified_class_name(class_name) do |fully_qualified_name|
89
+ begin
90
+ return eval(fully_qualified_name)
91
+ rescue NameError
92
+ end
93
+ end
94
+ raise SlimError.new("message:<<COULD_NOT_INVOKE_CONSTRUCTOR #{class_name} in any module #{@modules.inspect}>>")
95
+ end
96
+
97
+ def instance(instance_name)
98
+ @instances[instance_name]
99
+ end
100
+
101
+ def to_file_name(module_name)
102
+ value = module_name[0..0].downcase + module_name[1..-1]
103
+ value.gsub(/[A-Z]/) { |cap| "_#{cap.downcase}" }
104
+ end
105
+
106
+ def send_message_to_instance(instance, method, args)
107
+ symbols = replace_symbols(args)
108
+ instance.send(method, *replace_tables_with_hashes(symbols))
109
+ end
110
+
111
+ def method_to_call(instance, method_name)
112
+ return nil unless instance
113
+ return method_name.to_sym if instance.respond_to?(method_name)
114
+ return "#{$1}=".to_sym if method_name =~ /set_(\w+)/ && instance.respond_to?("#{$1}=")
115
+ return nil
116
+ end
117
+
118
+ def call(instance_name, method_name, *args)
119
+ begin
120
+ instance = self.instance(instance_name)
121
+ if method = method_to_call(instance, method_name)
122
+ send_message_to_instance(instance, method, args)
123
+ elsif instance.respond_to?(:sut) && method = method_to_call(instance.sut, method_name)
124
+ send_message_to_instance(instance.sut, method, args)
125
+ else
126
+ @libraries.reverse_each do |library|
127
+ method = method_to_call(library, method_name)
128
+ return send_message_to_instance(library, method, args) if method
129
+ end
130
+ raise SlimError.new("message:<<NO_INSTANCE #{instance_name}>>") if instance.nil?
131
+ raise SlimError.new("message:<<NO_METHOD_IN_CLASS #{method_name}[#{args.length}] #{instance.class.name}.>>")
132
+ end
133
+ rescue SlimError => e
134
+ Statement::EXCEPTION_TAG + e.to_s
135
+ end
136
+ end
137
+
138
+ def add_module(module_name)
139
+ @modules << module_name.gsub(/\./, '::')
140
+ end
141
+
142
+ def set_symbol(name, value)
143
+ @symbols[name] = value
144
+ end
145
+
146
+ def get_symbol(name)
147
+ @symbols[name]
148
+ end
149
+
150
+ def acquire_symbol(symbol_text)
151
+ symbol = get_symbol(symbol_text[1..-1])
152
+ symbol = symbol_text if symbol.nil?
153
+ symbol
154
+ end
155
+
156
+ def replace_symbol(item)
157
+ match = item.match(/\A\$\w*\z/)
158
+ return acquire_symbol(match[0]) if match
159
+
160
+ item.gsub(/\$\w*/) do |match|
161
+ acquire_symbol(match)
162
+ end
163
+ end
164
+
165
+ def replace_symbols(list)
166
+ list.map do |item|
167
+ if item.kind_of?(Array)
168
+ replace_symbols(item)
169
+ else
170
+ replace_symbol(item)
171
+ end
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,32 @@
1
+ require 'rexml/document'
2
+
3
+ class TableToHashConverter
4
+ def self.convert(string)
5
+ begin
6
+ doc = REXML::Document.new(string.strip)
7
+ return html_to_hash(doc)
8
+ rescue
9
+ return string
10
+ end
11
+ end
12
+
13
+ def self.html_to_hash(doc)
14
+ table = doc.elements['table']
15
+ raise ArgumentError if table.nil?
16
+ create_hash_from_rows(table)
17
+ end
18
+
19
+ def self.create_hash_from_rows(rows)
20
+ hash = {}
21
+ rows.elements.each('tr') do |row|
22
+ add_row_to_hash(hash, row)
23
+ end
24
+ hash
25
+ end
26
+
27
+ def self.add_row_to_hash(hash, row)
28
+ columns = row.get_elements('td')
29
+ raise ArgumentError if columns.size != 2
30
+ hash[columns[0].text.strip.to_sym] = columns[1].text.strip
31
+ end
32
+ end
@@ -0,0 +1,13 @@
1
+ module TestModule
2
+ class LibraryNew
3
+ attr_reader :called
4
+ attr_accessor :lib_attribute
5
+ def method_on_library_new
6
+ @called = true;
7
+ end
8
+
9
+ def a_method
10
+ @called = true;
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module TestModule
2
+ class LibraryOld
3
+ attr_reader :called
4
+ def method_on_library_old
5
+ @called = true;
6
+ end
7
+
8
+ def a_method
9
+ @called = true
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ module TestModule::ShouldNotFindTestSlimInHere
2
+ class TestSlim
3
+ def return_string
4
+ "blah"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ class SimpleScript
2
+ def set_arg(arg)
3
+ @arg = arg
4
+ end
5
+
6
+ def get_arg
7
+ @arg
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ class TestChain
2
+ def echo_boolean(b)
3
+ b
4
+ end
5
+ end
@@ -0,0 +1,86 @@
1
+ require 'ostruct'
2
+
3
+ module TestModule
4
+ class SystemUnderTest
5
+ attr_accessor :attribute
6
+ def sut_method
7
+ true
8
+ end
9
+ end
10
+
11
+ class TestSlim
12
+ attr_reader :sut
13
+ attr_accessor :string
14
+
15
+ def initialize(generation = 0)
16
+ @generation = generation
17
+ @sut = SystemUnderTest.new
18
+ @string = "string"
19
+ end
20
+
21
+ def return_string
22
+ @string
23
+ end
24
+
25
+ def returnString #Should not ever be called.
26
+ "blah"
27
+ end
28
+
29
+ def add(a, b)
30
+ a+b
31
+ end
32
+
33
+ def echo(x)
34
+ x
35
+ end
36
+
37
+ def null
38
+ nil
39
+ end
40
+
41
+ def echo_int i
42
+ i
43
+ end
44
+
45
+ def echo_string s
46
+ s
47
+ end
48
+
49
+ def syntax_error
50
+ eval "1,2"
51
+ end
52
+
53
+ def utf8
54
+ "Espa\357\277\275ol"
55
+ end
56
+
57
+ def create_test_slim_with_string(string)
58
+ slim = TestSlim.new(@generation + 1)
59
+ slim.string = string
60
+ slim
61
+ end
62
+
63
+ def new_with_string(string)
64
+ s = TestSlim.new
65
+ s.string = string
66
+ s
67
+ end
68
+
69
+ def echo_object(method, string)
70
+ OpenStruct.new(method.to_sym => string)
71
+ end
72
+
73
+ def call_on(method, object)
74
+ object.send(method.to_sym)
75
+ end
76
+
77
+ # def is_same(other)
78
+ # self === other
79
+ # end
80
+ #
81
+ # def get_string_from_other other
82
+ # other.get_string_arg
83
+ # end
84
+
85
+ end
86
+ end
@@ -0,0 +1,23 @@
1
+ module TestModule
2
+ class TestSlimWithArguments
3
+ def initialize(arg)
4
+ @arg = arg
5
+ end
6
+
7
+ def arg
8
+ @arg
9
+ end
10
+
11
+ def name
12
+ @arg[:name]
13
+ end
14
+
15
+ def addr
16
+ @arg[:addr]
17
+ end
18
+
19
+ def set_arg(hash)
20
+ @arg = hash
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,5 @@
1
+ module TestModule
2
+ class TestSlimWithNoSut
3
+
4
+ end
5
+ end
@@ -0,0 +1,25 @@
1
+
2
+ Gem::Specification.new do |s|
3
+ s.name = "rubyslim-unofficial"
4
+ s.version = "0.0.1"
5
+ s.summary = "Ruby SliM protocol for FitNesse"
6
+ s.description = <<-EOS
7
+ RubySliM implements the SliM protocol for the FitNesse acceptance testing
8
+ framework. This gem is an unofficial version created and distributed by
9
+ Eric Pierce <wapcaplet88@gmail.com>, based on the original code by Robert
10
+ C. Martin and Doug Bradbury.
11
+ EOS
12
+ s.authors = ["Robert C. Martin", "Doug Bradbury"]
13
+ s.email = "unclebob@cleancoder.com"
14
+ s.homepage = "http://github.com/wapcaplet/rubyslim"
15
+ s.platform = Gem::Platform::RUBY
16
+
17
+ s.add_development_dependency 'rspec', '~> 1.3.0'
18
+ s.add_development_dependency 'rcov'
19
+
20
+ s.files = `git ls-files`.split("\n")
21
+ s.require_path = 'lib'
22
+
23
+ s.executables = ['rubyslim']
24
+ end
25
+
@@ -0,0 +1,40 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
2
+ require "statement_executor"
3
+
4
+ describe StatementExecutor do
5
+ before do
6
+ @caller = StatementExecutor.new
7
+ end
8
+
9
+ it "can create an instance" do
10
+ response = @caller.create("x", "TestModule::TestSlim", [])
11
+ response.should == "OK"
12
+ x = @caller.instance("x")
13
+ x.class.name.should == "TestModule::TestSlim"
14
+ end
15
+
16
+ it "can create an instance with arguments" do
17
+ response = @caller.create("x", "TestModule::TestSlimWithArguments", ["3"])
18
+ response.should == "OK"
19
+ x = @caller.instance("x")
20
+ x.arg.should == "3"
21
+ end
22
+
23
+ it "can create an instance with arguments that are symbols" do
24
+ @caller.set_symbol("X", "3")
25
+ response = @caller.create("x", "TestModule::TestSlimWithArguments", ["$X"])
26
+ response.should == "OK"
27
+ x = @caller.instance("x")
28
+ x.arg.should == "3"
29
+ end
30
+
31
+ it "can't create an instance with the wrong number of arguments" do
32
+ result = @caller.create("x", "TestModule::TestSlim", ["1", "noSuchArgument"])
33
+ result.should include(Statement::EXCEPTION_TAG + "message:<<COULD_NOT_INVOKE_CONSTRUCTOR TestModule::TestSlim[2]>>")
34
+ end
35
+
36
+ it "can't create an instance if there is no class" do
37
+ result = @caller.create("x", "TestModule::NoSuchClass", [])
38
+ result.should include(Statement::EXCEPTION_TAG + "message:<<COULD_NOT_INVOKE_CONSTRUCTOR TestModule::NoSuchClass failed to find in []>>")
39
+ end
40
+ end
data/spec/it8f_spec.rb ADDED
@@ -0,0 +1,8 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
2
+
3
+ describe "characters" do
4
+ it "should be able to deal with it8f chars" do
5
+ "Köln".should == "Köln"
6
+ "Köln".size.should == 5
7
+ end
8
+ end
@@ -0,0 +1,66 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
2
+ require "list_serializer"
3
+ require "list_deserializer"
4
+
5
+ describe ListDeserializer do
6
+ before do
7
+ @list = []
8
+ end
9
+
10
+ it "can't deserialize a null string" do
11
+ proc {ListDeserializer.deserialize(nil)}.should raise_error(ListDeserializer::SyntaxError)
12
+ end
13
+
14
+ it "can't deserialize empty string" do
15
+ proc {ListDeserializer.deserialize("")}.should raise_error(ListDeserializer::SyntaxError)
16
+ end
17
+
18
+ it "can't deserialize string that doesn't start with an open bracket" do
19
+ proc {ListDeserializer.deserialize("hello")}.should raise_error(ListDeserializer::SyntaxError)
20
+ end
21
+
22
+ it "can't deserialize string that doesn't end with a bracket" do
23
+ proc {ListDeserializer.deserialize("[000000:")}.should raise_error(ListDeserializer::SyntaxError)
24
+ end
25
+
26
+ def check()
27
+ serialized = ListSerializer.serialize(@list)
28
+ deserialized = ListDeserializer.deserialize(serialized)
29
+ deserialized.should == @list
30
+ end
31
+
32
+ it "can deserialize and empty list" do
33
+ check
34
+ end
35
+
36
+ it "can deserialize a list with one element" do
37
+ @list = ["hello"]
38
+ check
39
+ end
40
+
41
+ it "can deserialize a list with two elements" do
42
+ @list = ["hello", "bob"]
43
+ check
44
+ end
45
+
46
+ it "can deserialize sublists" do
47
+ @list = ["hello", ["bob", "micah"], "today"]
48
+ check
49
+ end
50
+
51
+ it "can deserialize lists with multibyte strings" do
52
+ @list = ["Köln"]
53
+ check
54
+ end
55
+
56
+ it "can deserialize lists of strings that end with multibyte chars" do
57
+ @list = ["Kö"]
58
+ check
59
+ end
60
+
61
+ it "can deserialize lists with utf8" do
62
+ @list = ["123456789012345", "Espa\357\277\275ol"]
63
+ check
64
+ end
65
+
66
+ end