asir_xml 1.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +18 -0
- data/.rspec +1 -0
- data/.travis.yml +12 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +38 -0
- data/Rakefile +37 -0
- data/asir_xml.gemspec +26 -0
- data/example/ex01.rb +27 -0
- data/example/example_helper.rb +72 -0
- data/lib/asir/coder/xml.rb +215 -0
- data/lib/asir_xml/version.rb +3 -0
- data/lib/asir_xml.rb +5 -0
- data/spec/example_spec.rb +88 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/xml_spec.rb +144 -0
- metadata +150 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color -f d
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Kurt Stephens
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# asir_xml
|
2
|
+
|
3
|
+
[](https://travis-ci.org/kstephens/asir_xml)
|
5
|
+
[](https://codeclimate.com/github/kstephens/asir_xml)
|
7
|
+
|
8
|
+
XML Coder for ASIR
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
gem 'asir_xml'
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
$ bundle
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ gem install asir_xml
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
See example/.
|
27
|
+
|
28
|
+
## Dependencies
|
29
|
+
|
30
|
+
Requires install of libxml, libxslt for XML support: rake prereq.
|
31
|
+
|
32
|
+
## Contributing
|
33
|
+
|
34
|
+
1. Fork it
|
35
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
36
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
37
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
38
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
|
3
|
+
gem 'rspec'
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
|
6
|
+
######################################################################
|
7
|
+
|
8
|
+
desc "Default => :test"
|
9
|
+
task :default => :test
|
10
|
+
|
11
|
+
desc "Run all tests"
|
12
|
+
task :test => [ :spec ]
|
13
|
+
|
14
|
+
desc "Run specs"
|
15
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
16
|
+
t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
|
17
|
+
# Put spec opts in a file named .rspec in root
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "Generate code coverage"
|
21
|
+
RSpec::Core::RakeTask.new(:coverage) do |t|
|
22
|
+
t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
|
23
|
+
t.rcov = true
|
24
|
+
t.rcov_opts = ['--exclude', 'spec']
|
25
|
+
end
|
26
|
+
|
27
|
+
######################################################################
|
28
|
+
|
29
|
+
desc "Install system prerequites"
|
30
|
+
task :prereq do
|
31
|
+
case RUBY_PLATFORM
|
32
|
+
when /darwin/i
|
33
|
+
sh "sudo port install libxml libxslt"
|
34
|
+
when /linux/i
|
35
|
+
sh "sudo apt-get install libxml2-dev libxslt1-dev"
|
36
|
+
end
|
37
|
+
end
|
data/asir_xml.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'asir_xml/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "asir_xml"
|
8
|
+
gem.version = AsirXml::VERSION
|
9
|
+
gem.authors = ["Kurt Stephens"]
|
10
|
+
gem.email = ["ks.ruby@kurtstephens.com"]
|
11
|
+
gem.description = %q{XML Coder for ASIR}
|
12
|
+
gem.summary = %q{XML Coder for ASIR}
|
13
|
+
gem.homepage = "http://github.com/kstephens/abstracting_services_in_ruby"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_dependency "asir", "~> 1.1.10"
|
21
|
+
gem.add_dependency "libxml-ruby", "~> 2.3.3"
|
22
|
+
|
23
|
+
gem.add_development_dependency 'rake', '>= 0.9.0'
|
24
|
+
gem.add_development_dependency 'rspec', '~> 2.12.0'
|
25
|
+
gem.add_development_dependency 'simplecov', '>= 0.1'
|
26
|
+
end
|
data/example/ex01.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# !SLIDE :capture_code_output true
|
2
|
+
# Synchronous HTTP/XML service.
|
3
|
+
|
4
|
+
require 'example_helper'
|
5
|
+
module App; include ASIR::Client; end
|
6
|
+
begin
|
7
|
+
App.asir.transport = t =
|
8
|
+
ASIR::Transport::Webrick.new(:uri => "http://localhost:31913/")
|
9
|
+
t.encoder = ASIR::Coder::XML.new
|
10
|
+
server_process do
|
11
|
+
t.prepare_server!
|
12
|
+
t.run_server!
|
13
|
+
end
|
14
|
+
pr App.asir.eval("2 + 2")
|
15
|
+
sleep 1
|
16
|
+
rescue Object => err
|
17
|
+
$stderr.puts "#{err.inspect}\n#{err.backtrace * "\n"}"
|
18
|
+
ensure
|
19
|
+
t.close rescue nil; sleep 1
|
20
|
+
server_kill
|
21
|
+
end
|
22
|
+
|
23
|
+
# !SLIDE END
|
24
|
+
# EXPECT: : client process
|
25
|
+
# EXPECT: : server process
|
26
|
+
# EXPECT: : pr: 4
|
27
|
+
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# Sample client support
|
2
|
+
#
|
3
|
+
require 'rubygems'
|
4
|
+
case RUBY_PLATFORM
|
5
|
+
when /java/i
|
6
|
+
gem 'spoon'; require 'spoon'
|
7
|
+
end
|
8
|
+
|
9
|
+
$: << File.expand_path("../../lib", __FILE__)
|
10
|
+
require 'asir'
|
11
|
+
require 'asir/transport/webrick'
|
12
|
+
require 'asir/coder/xml'
|
13
|
+
ASIR::Log.enabled = true unless ENV['ASIR_EXAMPLE_SILENT']
|
14
|
+
|
15
|
+
require 'pp'
|
16
|
+
|
17
|
+
class ::Object
|
18
|
+
|
19
|
+
def pr result
|
20
|
+
$stdout.puts "*** #{$$}: pr: #{PP.pp(result, '')}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def server_process &blk
|
24
|
+
# $stderr.puts " at #{__FILE__}:#{__LINE__}"
|
25
|
+
case RUBY_PLATFORM
|
26
|
+
when /java/i
|
27
|
+
# JRuby cannot fork.
|
28
|
+
# So we must prevent spawn a new jruby and
|
29
|
+
# instruct it to only run the server blk, and not
|
30
|
+
# the subsequent client code.
|
31
|
+
# In other words, we cannot rely on how Process.fork
|
32
|
+
# terminates within the block.
|
33
|
+
if ENV['ASIR_JRUBY_SPAWNED']
|
34
|
+
$stderr.puts " spawned server at #{__FILE__}:#{__LINE__}"
|
35
|
+
puts "*** #{$$}: server process"; $stdout.flush
|
36
|
+
yield
|
37
|
+
Process.exit!(0)
|
38
|
+
# dont do client, client is our parent process.
|
39
|
+
else
|
40
|
+
$stderr.puts " spawning at #{__FILE__}:#{__LINE__}"
|
41
|
+
ENV['ASIR_JRUBY_SPAWNED'] = "1"
|
42
|
+
cmd = "ruby -I #{File.dirname(__FILE__)} -I #{File.expand_path('../../lib', __FILE__)} #{$0} #{ARGV * ' '}"
|
43
|
+
$stderr.puts " cmd = #{cmd}"
|
44
|
+
$server_pid = Spoon.spawnp(cmd)
|
45
|
+
ENV.delete('ASIR_JRUBY_SPAWNED')
|
46
|
+
$stderr.puts " spawned #{$server_pid} at #{__FILE__}:#{__LINE__}"
|
47
|
+
end
|
48
|
+
else
|
49
|
+
# $stderr.puts " at #{__FILE__}:#{__LINE__}"
|
50
|
+
$server_pid = Process.fork do
|
51
|
+
puts "*** #{$$}: server process"; $stdout.flush
|
52
|
+
yield
|
53
|
+
end
|
54
|
+
end
|
55
|
+
sleep 1 # wait for server to be ready.
|
56
|
+
return false # do client.
|
57
|
+
end
|
58
|
+
|
59
|
+
def server_kill
|
60
|
+
if $server_pid
|
61
|
+
Process.kill 9, $server_pid
|
62
|
+
Process.waitpid($server_pid)
|
63
|
+
end
|
64
|
+
rescue Errno::ESRCH
|
65
|
+
ensure
|
66
|
+
$server_pid = nil
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
puts "*** #{$$}: client process"; $stdout.flush
|
72
|
+
|
@@ -0,0 +1,215 @@
|
|
1
|
+
require 'asir'
|
2
|
+
require 'asir/object_resolving'
|
3
|
+
gem 'libxml-ruby'
|
4
|
+
require 'xml'
|
5
|
+
|
6
|
+
module ASIR
|
7
|
+
class Coder
|
8
|
+
# !SLIDE
|
9
|
+
# XML
|
10
|
+
#
|
11
|
+
# Encode/Decode objects as XML.
|
12
|
+
class XML < self
|
13
|
+
class Error < ::ASIR::Error
|
14
|
+
class BadIdref < self; end
|
15
|
+
end
|
16
|
+
def _encode obj
|
17
|
+
@stream = ''
|
18
|
+
@dom_id_map = { }
|
19
|
+
@dom_id = 0
|
20
|
+
@cls_tag_map = { }
|
21
|
+
encode_dom obj
|
22
|
+
@stream
|
23
|
+
end
|
24
|
+
|
25
|
+
def _decode obj
|
26
|
+
@stream = obj
|
27
|
+
@decoder ||= DECODER; @decoder_object = nil
|
28
|
+
@dom_id_map = { }
|
29
|
+
@dom_id = 0
|
30
|
+
@cls_tag_map = { }
|
31
|
+
@parser = ::XML::Parser.string(@stream)
|
32
|
+
@dom = @parser.parse
|
33
|
+
decode_dom @dom.root
|
34
|
+
end
|
35
|
+
|
36
|
+
def encode_dom obj
|
37
|
+
if dom_id = @dom_id_map[obj.object_id]
|
38
|
+
tag_obj(obj, nil, :idref => dom_id.first)
|
39
|
+
else
|
40
|
+
_encode_dom obj
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def _encode_dom obj
|
45
|
+
case obj
|
46
|
+
when NilClass, TrueClass, FalseClass
|
47
|
+
tag_obj(obj)
|
48
|
+
when Numeric
|
49
|
+
tag_obj(obj, nil, :v => obj.to_s)
|
50
|
+
when Symbol
|
51
|
+
tag_obj(obj) do
|
52
|
+
@stream << obj.to_s
|
53
|
+
end
|
54
|
+
when String
|
55
|
+
tag_obj(obj, :id) do
|
56
|
+
@stream << obj.to_s
|
57
|
+
end
|
58
|
+
when Array
|
59
|
+
tag_obj(obj, :id) do
|
60
|
+
obj.each do | elem |
|
61
|
+
encode_dom elem
|
62
|
+
end
|
63
|
+
end
|
64
|
+
when Hash
|
65
|
+
tag_obj(obj, :id) do
|
66
|
+
obj.each do | key, val |
|
67
|
+
encode_dom key
|
68
|
+
encode_dom val
|
69
|
+
end
|
70
|
+
end
|
71
|
+
else
|
72
|
+
tag_obj(obj, :id) do
|
73
|
+
obj.instance_variables.each do | attr |
|
74
|
+
val = obj.instance_variable_get(attr)
|
75
|
+
key = attr.to_s.sub(/^@/, '')
|
76
|
+
tag(key) do
|
77
|
+
encode_dom val
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def tag_obj obj, with_id = false, attrs = nil
|
85
|
+
if block_given?
|
86
|
+
tag(cls_tag(obj), with_id ? { with_id => map_obj_to_dom_id!(obj) } : nil) do
|
87
|
+
yield
|
88
|
+
end
|
89
|
+
else
|
90
|
+
tag(cls_tag(obj), attrs)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
CC = '::'.freeze; D = '.'.freeze
|
95
|
+
def cls_tag obj
|
96
|
+
obj = obj.class
|
97
|
+
@cls_tag_map[obj] ||= obj.name.gsub(CC, D).freeze
|
98
|
+
end
|
99
|
+
|
100
|
+
def map_obj_to_dom_id! obj
|
101
|
+
if dom_id = @dom_id_map[obj.object_id]
|
102
|
+
dom_id.first
|
103
|
+
else
|
104
|
+
@dom_id_map[obj.object_id] = [ @dom_id += 1, obj ]
|
105
|
+
@dom_id
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
B = '<'.freeze; S = ' '.freeze; E = '>'.freeze; SE = '/>'.freeze
|
110
|
+
BS = '</'.freeze; A = '='.freeze
|
111
|
+
def tag tag, attrs = nil
|
112
|
+
tag = tag.to_s
|
113
|
+
@stream << B << tag << S
|
114
|
+
if attrs
|
115
|
+
attrs.each do | key, val |
|
116
|
+
@stream << key.to_s << A << val.to_s.inspect << S
|
117
|
+
end
|
118
|
+
end
|
119
|
+
if block_given?
|
120
|
+
@stream << E; yield; @stream << BS << tag << E
|
121
|
+
else
|
122
|
+
@stream << SE
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
################################################################
|
127
|
+
|
128
|
+
def decode_dom dom
|
129
|
+
if dom_id = dom.attributes[:idref]
|
130
|
+
unless obj = @dom_id_map[dom_id]
|
131
|
+
raise Error::BadIdref, "in element #{dom}"
|
132
|
+
end
|
133
|
+
obj
|
134
|
+
else
|
135
|
+
obj = _decode_dom(dom)
|
136
|
+
map_dom_id_to_obj! dom, obj if dom.attributes[:id]
|
137
|
+
obj
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def _decode_dom dom
|
142
|
+
cls_name = dom.name
|
143
|
+
decoder = @decoder[cls_name] ||
|
144
|
+
(@decoder_object ||= @decoder['Object'])
|
145
|
+
raise Error, "BUG: " unless decoder
|
146
|
+
decoder.call(self, dom)
|
147
|
+
end
|
148
|
+
|
149
|
+
DECODER = {
|
150
|
+
'NilClass' => lambda { | _, dom | nil },
|
151
|
+
'TrueClass' => lambda { | _, dom | true },
|
152
|
+
'FalseClass' => lambda { | _, dom | false },
|
153
|
+
'String' => lambda { | _, dom | (dom.attributes[:v] || dom.content) },
|
154
|
+
'Symbol' => lambda { | _, dom | (dom.attributes[:v] || dom.content).to_sym },
|
155
|
+
'Integer' => lambda { | _, dom | (dom.attributes[:v] || dom.content).to_i },
|
156
|
+
'Float' => lambda { | _, dom | (dom.attributes[:v] || dom.content).to_f },
|
157
|
+
"Array" => lambda { | _, dom |
|
158
|
+
obj = [ ]
|
159
|
+
_.map_dom_id_to_obj! dom, obj
|
160
|
+
dom.each_element do | elem |
|
161
|
+
obj << _.decode_dom(elem)
|
162
|
+
end
|
163
|
+
obj
|
164
|
+
},
|
165
|
+
'Hash' => lambda { | _, dom |
|
166
|
+
obj = { }
|
167
|
+
_.map_dom_id_to_obj! dom, obj
|
168
|
+
key = nil
|
169
|
+
dom.each_element do | val |
|
170
|
+
if key
|
171
|
+
obj[_.decode_dom(key)] = _.decode_dom(val)
|
172
|
+
key = nil
|
173
|
+
else
|
174
|
+
key = val
|
175
|
+
end
|
176
|
+
end
|
177
|
+
obj
|
178
|
+
},
|
179
|
+
'Object' => lambda { | _, dom |
|
180
|
+
cls_name = dom.name
|
181
|
+
# $stderr.puts "cls_name = #{cls_name.inspect}"
|
182
|
+
cls = _.tag_cls(cls_name)
|
183
|
+
obj = cls.allocate
|
184
|
+
_.map_dom_id_to_obj! dom, obj
|
185
|
+
dom.each_element do | child |
|
186
|
+
key = child.name
|
187
|
+
val = _.decode_dom child.first
|
188
|
+
obj.instance_variable_set("@#{key}", val)
|
189
|
+
end
|
190
|
+
obj
|
191
|
+
},
|
192
|
+
}
|
193
|
+
DECODER['Fixnum'] = DECODER['Bignum'] = DECODER['Integer']
|
194
|
+
|
195
|
+
def map_dom_id_to_obj! dom, obj
|
196
|
+
dom_id = dom.attributes[:id]
|
197
|
+
debugger unless dom_id
|
198
|
+
raise Error, "no :id attribute in #{dom}" unless dom_id
|
199
|
+
if (other_obj = @dom_id_map[dom_id]) and other_obj.object_id != obj.object_id
|
200
|
+
raise Error, "BUG: :id #{dom_id} already used for #{other_obj.class.name} #{other_obj.inspect}"
|
201
|
+
end
|
202
|
+
@dom_id_map[dom_id] = obj
|
203
|
+
end
|
204
|
+
|
205
|
+
include ObjectResolving
|
206
|
+
def tag_cls cls_name
|
207
|
+
@cls_tag_map[cls_name.freeze] ||= resolve_object(cls_name.gsub('.', '::'))
|
208
|
+
end
|
209
|
+
|
210
|
+
# This coder is stateful.
|
211
|
+
def prepare; dup; end
|
212
|
+
end
|
213
|
+
# !SLIDE END
|
214
|
+
end
|
215
|
+
end
|
data/lib/asir_xml.rb
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
require File.expand_path('../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
$:.unshift File.expand_path('../../example', __FILE__)
|
4
|
+
|
5
|
+
describe "ASIR Example" do
|
6
|
+
attr_accessor :file, :expects
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
@expects = [ ]
|
10
|
+
end
|
11
|
+
|
12
|
+
after(:each) do
|
13
|
+
@file.should_not == nil
|
14
|
+
File.open(@file) do | fh |
|
15
|
+
until fh.eof?
|
16
|
+
line = fh.readline
|
17
|
+
line.chomp!
|
18
|
+
case
|
19
|
+
when line.sub!(/^\s*#\s*EXPECT\/:\s*/, '')
|
20
|
+
expect Regexp.new(line)
|
21
|
+
when line.sub!(/^\s*#\s*EXPECT!\/:\s*/, '')
|
22
|
+
expect Regexp.new(line), :'!~'
|
23
|
+
when line.sub!(/^\s*#\s*EXPECT:\s*/, '')
|
24
|
+
expect Regexp.new(Regexp.escape(line))
|
25
|
+
when line.sub!(/^\s*#\s*EXPECT!:\s*/, '')
|
26
|
+
expect Regexp.new(Regexp.escape(line)), :'!~'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
@output, @exit_code = run_file!(@file)
|
31
|
+
@exit_code.should == 0
|
32
|
+
@expects.empty?.should_not == true
|
33
|
+
@expects.each do | rx, mode |
|
34
|
+
$stderr.puts " Checking #{mode} #{rx.inspect}" if ENV['SPEC_VERBOSE']
|
35
|
+
case mode
|
36
|
+
when :'=~'
|
37
|
+
@output.should =~ rx
|
38
|
+
when :'!~'
|
39
|
+
@output.should_not =~ rx
|
40
|
+
else
|
41
|
+
raise ArgumentError
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def run_file! file, output = StringIO.new('')
|
47
|
+
progname_save, stdout_save, stderr_save = $0, $stdout, $stderr
|
48
|
+
exc = system_exit = nil; exit_code = 0
|
49
|
+
begin
|
50
|
+
if true
|
51
|
+
cmd = "ASIR_EXAMPLE_SILENT=1 ruby -I example -I lib #{file}"
|
52
|
+
$stderr.puts "\n Running #{cmd}:" if ENV['SPEC_VERBOSE']
|
53
|
+
output = `#{cmd} 2>&1 | tee #{file}.out`
|
54
|
+
else
|
55
|
+
$stderr.puts "\n Loading #{file}:" if ENV['SPEC_VERBOSE']
|
56
|
+
$stdout.puts "*** #{$$}: client process"; $stdout.flush
|
57
|
+
$stdout = $stderr = output
|
58
|
+
$0 = file
|
59
|
+
Kernel.load(file, true)
|
60
|
+
output = output.string if StringIO === output
|
61
|
+
end
|
62
|
+
rescue ::SystemExit => system_exit
|
63
|
+
exit_code = 1 # ???
|
64
|
+
rescue ::Exception => exc
|
65
|
+
exit_code = -1
|
66
|
+
end
|
67
|
+
[ output, exit_code ]
|
68
|
+
ensure
|
69
|
+
$0, $stdout, $stderr = progname_save, stdout_save, stderr_save
|
70
|
+
$stderr.write output if ENV['SPEC_VERBOSE']
|
71
|
+
if exc
|
72
|
+
stderr_save.puts "ERROR: #{file}: #{exc.inspect}\n#{exc.backtrace * "\n"}"
|
73
|
+
raise exc
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def expect rx, mode = :'=~'
|
78
|
+
@expects << [ rx, mode ]
|
79
|
+
end
|
80
|
+
|
81
|
+
Dir['example/**/ex[0-9]*.rb'].sort.each do | file |
|
82
|
+
title = File.open(file) { | fh | fh.read(4096) }
|
83
|
+
title = title =~ /#\s+!SLIDE[^\n]*\n\s*#\s*([^\n]+)/ && $1
|
84
|
+
it "#{file} - #{title}" do
|
85
|
+
@file = file
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
data/spec/spec_helper.rb
ADDED
data/spec/xml_spec.rb
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
require File.expand_path('../spec_helper', __FILE__)
|
2
|
+
require 'asir/coder/xml'
|
3
|
+
|
4
|
+
describe "ASIR::Coder::XML" do
|
5
|
+
before(:each) do
|
6
|
+
@enc = ASIR::Coder::XML.new
|
7
|
+
@dec = @enc.dup
|
8
|
+
end
|
9
|
+
|
10
|
+
basic_objs = [ ]
|
11
|
+
|
12
|
+
[
|
13
|
+
nil,
|
14
|
+
true,
|
15
|
+
false,
|
16
|
+
].each do | x |
|
17
|
+
basic_objs << x
|
18
|
+
it "should handle #{x.inspect}" do
|
19
|
+
xml = @enc.prepare.encode(x)
|
20
|
+
xml.should == "<#{x.class.name} />"
|
21
|
+
@dec.prepare.decode(xml).should == x
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
[
|
26
|
+
1234,
|
27
|
+
1.234,
|
28
|
+
].each do | x |
|
29
|
+
basic_objs << x
|
30
|
+
it "should handle #{x.inspect}" do
|
31
|
+
xml = @enc.prepare.encode(x)
|
32
|
+
xml.should == "<#{x.class.name} v=\"#{x.to_s}\" />"
|
33
|
+
@dec.prepare.decode(xml).should == x
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
[
|
38
|
+
:symbol,
|
39
|
+
].each do | x |
|
40
|
+
basic_objs << x
|
41
|
+
it "should handle #{x.inspect}" do
|
42
|
+
xml = @enc.prepare.encode(x)
|
43
|
+
xml.should == "<#{x.class.name} >#{x.to_s}</#{x.class.name}>"
|
44
|
+
@dec.prepare.decode(xml).should == x
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
[
|
49
|
+
'String',
|
50
|
+
].each do | x |
|
51
|
+
basic_objs << x
|
52
|
+
it "should handle #{x.inspect}" do
|
53
|
+
xml = @enc.prepare.encode(x)
|
54
|
+
xml.should == "<#{x.class.name} id=\"1\" >#{x.to_s}</#{x.class.name}>"
|
55
|
+
@dec.prepare.decode(xml).should == x
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should handle empty Array" do
|
60
|
+
x = [ ]
|
61
|
+
xml = @enc.prepare.encode(x)
|
62
|
+
xml.should == "<#{x.class.name} id=\"1\" ></#{x.class.name}>"
|
63
|
+
@dec.prepare.decode(xml).should == x
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should handle Array" do
|
67
|
+
x = [ *basic_objs ]
|
68
|
+
xml = @enc.prepare.encode(x)
|
69
|
+
xml.should =~ %r{\A<#{x.class.name} id=\"1\" ><NilClass /><TrueClass /><FalseClass /><Fixnum v="1234" /><Float v="1.234" /><Symbol >symbol</Symbol><String id=\"[^"]+\" >String</String></#{x.class.name}>\Z} # " emacs
|
70
|
+
@dec.prepare.decode(xml).should == x
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should handle empty Hash" do
|
74
|
+
x = { }
|
75
|
+
xml = @enc.prepare.encode(x)
|
76
|
+
xml.should == "<#{x.class.name} id=\"1\" ></#{x.class.name}>"
|
77
|
+
@dec.prepare.decode(xml).should == x
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should handle Hash" do
|
81
|
+
x = Hash[ *basic_objs.map{|e| e.inspect}.zip(basic_objs).flatten ]
|
82
|
+
xml = @enc.prepare.encode(x)
|
83
|
+
xml.should =~ %r{\A<#{x.class.name} id=\"1\" >}
|
84
|
+
xml.should =~ %r{</#{x.class.name}>\Z}
|
85
|
+
basic_objs.each do | v |
|
86
|
+
vx = @enc.dup.encode(v)
|
87
|
+
vx = vx.gsub(/id="[^"]+"/, 'id="\d+"')
|
88
|
+
xml.should =~ Regexp.new(vx)
|
89
|
+
xml.should =~ %r{ >#{v.inspect}</String>}
|
90
|
+
end
|
91
|
+
@dec.prepare.decode(xml).should == x
|
92
|
+
end
|
93
|
+
|
94
|
+
class ASIR::Coder::XML::Test
|
95
|
+
attr_accessor :a, :h, :o
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should handle deep objects" do
|
99
|
+
x = ASIR::Coder::XML::Test.new
|
100
|
+
x.a = [ *basic_objs ]
|
101
|
+
x.h = Hash[ *basic_objs.map{|e| e.inspect}.zip(basic_objs).flatten ]
|
102
|
+
x.o = ASIR::Coder::XML::Test.new
|
103
|
+
x.o.a = 123
|
104
|
+
xml = @enc.prepare.encode(x)
|
105
|
+
xml.should =~ %r{<#{x.class.name.gsub('::', '.')} id=\"1\" >}
|
106
|
+
xml.should =~ %r{</#{x.class.name.gsub('::', '.')}>}
|
107
|
+
y = @dec.prepare.decode(xml)
|
108
|
+
y.a.should == x.a
|
109
|
+
y.h.should == x.h
|
110
|
+
y.o.class.should == ASIR::Coder::XML::Test
|
111
|
+
y.o.a.should == x.o.a
|
112
|
+
x.instance_variables.sort { |a, b| a.to_s <=> b.to_s}.should ==
|
113
|
+
y.instance_variables.sort { | a, b | a.to_s <=> b.to_s }
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should handle multiple references to same objects." do
|
117
|
+
x = Hash[ *basic_objs.map{|e| e.inspect}.zip(basic_objs).flatten ]
|
118
|
+
y = [ 1, 2 ]
|
119
|
+
x = [ x, x, y, y ]
|
120
|
+
xml = @enc.prepare.encode(x)
|
121
|
+
y = @dec.prepare.decode(xml)
|
122
|
+
y[0].object_id.should == y[1].object_id
|
123
|
+
y[2].object_id.should == y[3].object_id
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should handle self-referencing Array." do
|
127
|
+
x = [ 1 ]
|
128
|
+
x << x
|
129
|
+
xml = @enc.prepare.encode(x)
|
130
|
+
y = @dec.prepare.decode(xml)
|
131
|
+
y[0].should == x[0]
|
132
|
+
y[1].object_id.should == y.object_id
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should handle self-referencing Hash." do
|
136
|
+
x = { :a => 1 }
|
137
|
+
x[:self] = x
|
138
|
+
xml = @enc.prepare.encode(x)
|
139
|
+
y = @dec.prepare.decode(xml)
|
140
|
+
y[:a].should == x[:a]
|
141
|
+
y[:self].object_id.should == y.object_id
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
metadata
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: asir_xml
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.1.10
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Kurt Stephens
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-12-29 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: asir
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.1.10
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.1.10
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: libxml-ruby
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 2.3.3
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 2.3.3
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rake
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.9.0
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.9.0
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rspec
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 2.12.0
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 2.12.0
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: simplecov
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0.1'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0.1'
|
94
|
+
description: XML Coder for ASIR
|
95
|
+
email:
|
96
|
+
- ks.ruby@kurtstephens.com
|
97
|
+
executables: []
|
98
|
+
extensions: []
|
99
|
+
extra_rdoc_files: []
|
100
|
+
files:
|
101
|
+
- .gitignore
|
102
|
+
- .rspec
|
103
|
+
- .travis.yml
|
104
|
+
- Gemfile
|
105
|
+
- LICENSE.txt
|
106
|
+
- README.md
|
107
|
+
- Rakefile
|
108
|
+
- asir_xml.gemspec
|
109
|
+
- example/ex01.rb
|
110
|
+
- example/example_helper.rb
|
111
|
+
- lib/asir/coder/xml.rb
|
112
|
+
- lib/asir_xml.rb
|
113
|
+
- lib/asir_xml/version.rb
|
114
|
+
- spec/example_spec.rb
|
115
|
+
- spec/spec_helper.rb
|
116
|
+
- spec/xml_spec.rb
|
117
|
+
homepage: http://github.com/kstephens/abstracting_services_in_ruby
|
118
|
+
licenses: []
|
119
|
+
post_install_message:
|
120
|
+
rdoc_options: []
|
121
|
+
require_paths:
|
122
|
+
- lib
|
123
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
124
|
+
none: false
|
125
|
+
requirements:
|
126
|
+
- - ! '>='
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
segments:
|
130
|
+
- 0
|
131
|
+
hash: 4528790535439235638
|
132
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
133
|
+
none: false
|
134
|
+
requirements:
|
135
|
+
- - ! '>='
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
segments:
|
139
|
+
- 0
|
140
|
+
hash: 4528790535439235638
|
141
|
+
requirements: []
|
142
|
+
rubyforge_project:
|
143
|
+
rubygems_version: 1.8.24
|
144
|
+
signing_key:
|
145
|
+
specification_version: 3
|
146
|
+
summary: XML Coder for ASIR
|
147
|
+
test_files:
|
148
|
+
- spec/example_spec.rb
|
149
|
+
- spec/spec_helper.rb
|
150
|
+
- spec/xml_spec.rb
|