asir 0.2.0
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 +11 -0
- data/Gemfile +16 -0
- data/README.textile +50 -0
- data/Rakefile +83 -0
- data/VERSION +1 -0
- data/asir.gemspec +36 -0
- data/asir.riterate.yml +114 -0
- data/bin/asir +6 -0
- data/doc/Rakefile +8 -0
- data/doc/asir-sequence.pic +84 -0
- data/doc/asir-sequence.svg +1559 -0
- data/doc/sequence.pic +430 -0
- data/example/asir_control.sh +24 -0
- data/example/asir_control_client_http.rb +14 -0
- data/example/asir_control_client_zmq.rb +15 -0
- data/example/config/asir_config.rb +63 -0
- data/example/delayed_service.rb +15 -0
- data/example/ex01.rb +12 -0
- data/example/ex02.rb +12 -0
- data/example/ex03.rb +19 -0
- data/example/ex04.rb +33 -0
- data/example/ex05.rb +16 -0
- data/example/ex06.rb +26 -0
- data/example/ex07.rb +28 -0
- data/example/ex08.rb +30 -0
- data/example/ex09.rb +25 -0
- data/example/ex10.rb +24 -0
- data/example/ex11.rb +48 -0
- data/example/ex12.rb +34 -0
- data/example/ex13.rb +35 -0
- data/example/ex14.rb +30 -0
- data/example/ex15.rb +13 -0
- data/example/ex16.rb +33 -0
- data/example/ex17.rb +41 -0
- data/example/ex18.rb +62 -0
- data/example/ex19.rb +32 -0
- data/example/ex20.rb +28 -0
- data/example/ex21.rb +28 -0
- data/example/ex22.rb +15 -0
- data/example/ex23.rb +20 -0
- data/example/ex24.rb +35 -0
- data/example/example_helper.rb +51 -0
- data/example/sample_service.rb +162 -0
- data/example/unsafe_service.rb +12 -0
- data/hack_night/README.txt +18 -0
- data/hack_night/exercise/prob-1.rb +18 -0
- data/hack_night/exercise/prob-2.rb +21 -0
- data/hack_night/exercise/prob-3.rb +16 -0
- data/hack_night/exercise/prob-4.rb +36 -0
- data/hack_night/exercise/prob-5.rb +36 -0
- data/hack_night/exercise/prob-6.rb +95 -0
- data/hack_night/exercise/prob-7.rb +34 -0
- data/hack_night/solution/math_service.rb +11 -0
- data/hack_night/solution/prob-1.rb +12 -0
- data/hack_night/solution/prob-2.rb +15 -0
- data/hack_night/solution/prob-3.rb +17 -0
- data/hack_night/solution/prob-4.rb +37 -0
- data/hack_night/solution/prob-5.rb +21 -0
- data/hack_night/solution/prob-6.rb +33 -0
- data/hack_night/solution/prob-7.rb +36 -0
- data/lab/phony_proc.rb +31 -0
- data/lib/asir.rb +253 -0
- data/lib/asir/additional_data.rb +25 -0
- data/lib/asir/channel.rb +130 -0
- data/lib/asir/client.rb +111 -0
- data/lib/asir/code_block.rb +57 -0
- data/lib/asir/code_more.rb +50 -0
- data/lib/asir/coder.rb +26 -0
- data/lib/asir/coder/base64.rb +19 -0
- data/lib/asir/coder/chain.rb +30 -0
- data/lib/asir/coder/identity.rb +23 -0
- data/lib/asir/coder/json.rb +30 -0
- data/lib/asir/coder/marshal.rb +17 -0
- data/lib/asir/coder/null.rb +23 -0
- data/lib/asir/coder/proc.rb +22 -0
- data/lib/asir/coder/sign.rb +48 -0
- data/lib/asir/coder/xml.rb +213 -0
- data/lib/asir/coder/yaml.rb +33 -0
- data/lib/asir/coder/zlib.rb +21 -0
- data/lib/asir/configuration.rb +32 -0
- data/lib/asir/error.rb +34 -0
- data/lib/asir/identity.rb +36 -0
- data/lib/asir/initialization.rb +23 -0
- data/lib/asir/log.rb +82 -0
- data/lib/asir/main.rb +396 -0
- data/lib/asir/message.rb +31 -0
- data/lib/asir/message/delay.rb +35 -0
- data/lib/asir/object_resolving.rb +15 -0
- data/lib/asir/result.rb +39 -0
- data/lib/asir/retry_behavior.rb +54 -0
- data/lib/asir/transport.rb +241 -0
- data/lib/asir/transport/beanstalk.rb +217 -0
- data/lib/asir/transport/broadcast.rb +34 -0
- data/lib/asir/transport/buffer.rb +115 -0
- data/lib/asir/transport/composite.rb +19 -0
- data/lib/asir/transport/connection_oriented.rb +180 -0
- data/lib/asir/transport/delay.rb +38 -0
- data/lib/asir/transport/delegation.rb +53 -0
- data/lib/asir/transport/fallback.rb +36 -0
- data/lib/asir/transport/file.rb +88 -0
- data/lib/asir/transport/http.rb +54 -0
- data/lib/asir/transport/local.rb +21 -0
- data/lib/asir/transport/null.rb +14 -0
- data/lib/asir/transport/payload_io.rb +52 -0
- data/lib/asir/transport/rack.rb +73 -0
- data/lib/asir/transport/retry.rb +41 -0
- data/lib/asir/transport/stream.rb +35 -0
- data/lib/asir/transport/subprocess.rb +30 -0
- data/lib/asir/transport/tcp_socket.rb +34 -0
- data/lib/asir/transport/webrick.rb +50 -0
- data/lib/asir/transport/zmq.rb +110 -0
- data/lib/asir/uuid.rb +32 -0
- data/lib/asir/version.rb +3 -0
- data/spec/const_get_speed_spec.rb +33 -0
- data/spec/debug_helper.rb +20 -0
- data/spec/example_spec.rb +88 -0
- data/spec/json_spec.rb +128 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/xml_spec.rb +144 -0
- data/stylesheets/slides.css +105 -0
- metadata +173 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require 'asir/transport/http'
|
|
2
|
+
require 'webrick'
|
|
3
|
+
|
|
4
|
+
module ASIR
|
|
5
|
+
class Transport
|
|
6
|
+
# !SLIDE
|
|
7
|
+
# WEBrick Transport server.
|
|
8
|
+
class Webrick < HTTP
|
|
9
|
+
|
|
10
|
+
# Server-side: WEBrick
|
|
11
|
+
|
|
12
|
+
# Receive the Message payload String from the HTTP Message object.
|
|
13
|
+
# Returns the original http_message as the message_state.
|
|
14
|
+
def _receive_message http_message, additional_data
|
|
15
|
+
[ http_message.body, http_message ]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Send the Result payload String in the HTTP Response object as application/binary.
|
|
19
|
+
def _send_result message, result, result_payload, http_result, message_state
|
|
20
|
+
http_result[CONTENT_TYPE] = APPLICATION_BINARY
|
|
21
|
+
http_result.body = result_payload
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def prepare_server! opts = { }
|
|
25
|
+
u = URI.parse(uri)
|
|
26
|
+
port = u.port
|
|
27
|
+
path = u.path
|
|
28
|
+
opts[:Port] ||= port
|
|
29
|
+
@server = ::WEBrick::HTTPServer.new(opts)
|
|
30
|
+
@server.mount_proc path, lambda { | rq, rs |
|
|
31
|
+
serve_message! rq, rs
|
|
32
|
+
}
|
|
33
|
+
self
|
|
34
|
+
rescue ::Exception => exc
|
|
35
|
+
raise Error, "Webrick Server #{uri.inspect}: #{exc.inspect}", exc.backtrace
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def run_server!
|
|
39
|
+
@server.start
|
|
40
|
+
self
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def stop_server!
|
|
44
|
+
@server.stop
|
|
45
|
+
self
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
# !SLIDE END
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
require 'asir/transport/connection_oriented'
|
|
2
|
+
gem 'zmq'
|
|
3
|
+
require 'zmq'
|
|
4
|
+
|
|
5
|
+
module ASIR
|
|
6
|
+
class Transport
|
|
7
|
+
# !SLIDE
|
|
8
|
+
# ZeroMQ Transport
|
|
9
|
+
class Zmq < ConnectionOriented
|
|
10
|
+
attr_accessor :queue
|
|
11
|
+
|
|
12
|
+
# !SLIDE
|
|
13
|
+
# 0MQ client.
|
|
14
|
+
def _client_connect!
|
|
15
|
+
sock = zmq_context.socket(one_way ? ZMQ::PUB : ZMQ::REQ)
|
|
16
|
+
sock.connect(zmq_uri)
|
|
17
|
+
sock
|
|
18
|
+
rescue ::Exception => exc
|
|
19
|
+
raise exc.class, "#{self.class} #{zmq_uri}: #{exc.message}", exc.backtrace
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# !SLIDE
|
|
23
|
+
# 0MQ server.
|
|
24
|
+
def _server!
|
|
25
|
+
sock = zmq_context.socket(one_way ? ZMQ::SUB : ZMQ::REP)
|
|
26
|
+
sock.setsockopt(ZMQ::SUBSCRIBE, queue) if one_way
|
|
27
|
+
sock.bind("tcp://*:#{port}") # WTF?: why doesn't tcp://localhost:PORT work?
|
|
28
|
+
@server = sock
|
|
29
|
+
rescue ::Exception => exc
|
|
30
|
+
raise exc.class, "#{self.class} #{zmq_uri}: #{exc.message}", exc.backtrace
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def _receive_result message, opaque_result
|
|
34
|
+
return nil if one_way || message.one_way
|
|
35
|
+
super
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def _send_result message, result, result_payload, stream, message_state
|
|
39
|
+
return nil if one_way || message.one_way
|
|
40
|
+
super
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def _write payload, stream
|
|
44
|
+
payload.insert(0, queue_) if one_way
|
|
45
|
+
stream.send payload, 0
|
|
46
|
+
stream
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def _read stream
|
|
50
|
+
stream.recv 0
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# def scheme; SCHEME; end; SCHEME = 'tcp'.freeze
|
|
54
|
+
def queue
|
|
55
|
+
@queue ||=
|
|
56
|
+
(
|
|
57
|
+
case
|
|
58
|
+
when @uri
|
|
59
|
+
x = URI.parse(@uri).path
|
|
60
|
+
else
|
|
61
|
+
x = ""
|
|
62
|
+
end
|
|
63
|
+
# x << "\t" unless x.empty?
|
|
64
|
+
x.freeze
|
|
65
|
+
)
|
|
66
|
+
end
|
|
67
|
+
def queue_
|
|
68
|
+
@queue_ ||=
|
|
69
|
+
(queue.empty? ? queue : queue + " ").freeze
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def run_server!
|
|
74
|
+
_log { "run_server! #{uri}" } if @verbose >= 1
|
|
75
|
+
with_server_signals! do
|
|
76
|
+
@running = true
|
|
77
|
+
while @running
|
|
78
|
+
begin
|
|
79
|
+
serve_stream_message!(@server, @one_way ? nil : @server)
|
|
80
|
+
rescue Error::Terminate => err
|
|
81
|
+
@running = false
|
|
82
|
+
_log [ :run_server_terminate, err ]
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
self
|
|
87
|
+
ensure
|
|
88
|
+
_server_close!
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def zmq_uri
|
|
92
|
+
@zmq_uri ||=
|
|
93
|
+
(
|
|
94
|
+
u = URI.parse(uri)
|
|
95
|
+
u.path = ''
|
|
96
|
+
u.to_s.freeze
|
|
97
|
+
)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def zmq_context
|
|
101
|
+
@@zmq_context ||=
|
|
102
|
+
ZMQ::Context.new(1)
|
|
103
|
+
end
|
|
104
|
+
@@zmq_context ||= nil
|
|
105
|
+
end
|
|
106
|
+
# !SLIDE END
|
|
107
|
+
end # class
|
|
108
|
+
end # module
|
|
109
|
+
|
|
110
|
+
|
data/lib/asir/uuid.rb
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module ASIR
|
|
2
|
+
# Provides an RFC4122-compliant random (version 4) UUID service.
|
|
3
|
+
module UUID
|
|
4
|
+
# Return an RFC4122-compliant random (version 4) UUID,
|
|
5
|
+
# represented as a string of 36 characters.
|
|
6
|
+
#
|
|
7
|
+
# Possible (but unlikely!) return value:
|
|
8
|
+
# "e29fc859-8d6d-4c5d-aa5a-1ab726f4a192".
|
|
9
|
+
#
|
|
10
|
+
# Possible exceptions:
|
|
11
|
+
# Errno::ENOENT
|
|
12
|
+
#
|
|
13
|
+
PROC_SYS_FILE = "/proc/sys/kernel/random/uuid".freeze
|
|
14
|
+
case
|
|
15
|
+
when File.exist?(PROC_SYS_FILE)
|
|
16
|
+
def self.generate
|
|
17
|
+
File.read(PROC_SYS_FILE).chomp!
|
|
18
|
+
end
|
|
19
|
+
when (gem 'uuid' rescue nil)
|
|
20
|
+
require 'uuid'
|
|
21
|
+
def self.generate
|
|
22
|
+
::UUID.generate
|
|
23
|
+
end
|
|
24
|
+
else
|
|
25
|
+
def self.generate
|
|
26
|
+
raise "Unimplemented"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
|
data/lib/asir/version.rb
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module ASIR
|
|
2
|
+
module Test
|
|
3
|
+
module NamespaceCost
|
|
4
|
+
module Relative
|
|
5
|
+
def self.m
|
|
6
|
+
Exception
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
module Absolute
|
|
10
|
+
def self.m
|
|
11
|
+
::Exception
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe 'Namespace Costs' do
|
|
19
|
+
it "uses dynamic namespacing" do
|
|
20
|
+
do_it ::ASIR::Test::NamespaceCost::Relative
|
|
21
|
+
end
|
|
22
|
+
it "uses static namespacing" do
|
|
23
|
+
do_it ::ASIR::Test::NamespaceCost::Absolute
|
|
24
|
+
end
|
|
25
|
+
def do_it obj
|
|
26
|
+
t0 = Time.now
|
|
27
|
+
10_000_000.times do
|
|
28
|
+
obj.m
|
|
29
|
+
end
|
|
30
|
+
t1 = Time.now
|
|
31
|
+
puts "#{obj} #{t1.to_f - t0.to_f}"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
case (RUBY_PLATFORM rescue 'UNKNOWN')
|
|
3
|
+
when /java/
|
|
4
|
+
gem 'json_pure'
|
|
5
|
+
else
|
|
6
|
+
gem 'json'
|
|
7
|
+
case RUBY_VERSION
|
|
8
|
+
when /^2\./
|
|
9
|
+
gem 'simplecov'
|
|
10
|
+
when /^1\.9/
|
|
11
|
+
gem 'ruby-debug19'
|
|
12
|
+
gem 'simplecov'
|
|
13
|
+
# require 'ruby-debug' # BROKEN in 1.9.3-head
|
|
14
|
+
when /^1\.8/
|
|
15
|
+
gem 'ruby-debug'
|
|
16
|
+
gem 'rcov'
|
|
17
|
+
require 'ruby-debug'
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
@@ -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/json_spec.rb
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
require File.expand_path('../spec_helper', __FILE__)
|
|
2
|
+
require 'asir/coder/json'
|
|
3
|
+
|
|
4
|
+
describe "ASIR::Coder::JSON" do
|
|
5
|
+
# unless RUBY_PLATFORM =~ /java/
|
|
6
|
+
before(:each) do
|
|
7
|
+
@enc = ASIR::Coder::JSON.new
|
|
8
|
+
@dec = @enc.dup
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
basic_objs = [ ]
|
|
12
|
+
|
|
13
|
+
[
|
|
14
|
+
[ nil, 'null' ],
|
|
15
|
+
true,
|
|
16
|
+
false,
|
|
17
|
+
].each do | x |
|
|
18
|
+
x, str = *x
|
|
19
|
+
str ||= x.inspect
|
|
20
|
+
str = "[#{str}]"
|
|
21
|
+
basic_objs << [ x, str ]
|
|
22
|
+
it "should handle #{x.inspect}" do
|
|
23
|
+
out = @enc.encode(x)
|
|
24
|
+
out.should == str
|
|
25
|
+
@dec.decode(out).should == x
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
[
|
|
30
|
+
1234,
|
|
31
|
+
1.234,
|
|
32
|
+
[ :symbol, '"symbol"' ],
|
|
33
|
+
].each do | x |
|
|
34
|
+
x, str = *x
|
|
35
|
+
str ||= x.inspect
|
|
36
|
+
str = "[#{str}]"
|
|
37
|
+
basic_objs << [ x, str ]
|
|
38
|
+
it "should handle #{x.inspect}" do
|
|
39
|
+
out = @enc.encode(x)
|
|
40
|
+
out.should == str
|
|
41
|
+
y = @dec.decode(out)
|
|
42
|
+
y = y.to_sym if Symbol === x
|
|
43
|
+
y.should == x
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
[
|
|
48
|
+
'String',
|
|
49
|
+
].each do | x |
|
|
50
|
+
x, str = *x
|
|
51
|
+
str ||= x.inspect
|
|
52
|
+
str = "[#{str}]"
|
|
53
|
+
basic_objs << [ x, str ]
|
|
54
|
+
it "should handle #{x.inspect}" do
|
|
55
|
+
out = @enc.encode(x)
|
|
56
|
+
out.should == str
|
|
57
|
+
y = @dec.decode(out)
|
|
58
|
+
y.should == x
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "should handle empty Array" do
|
|
63
|
+
x = [ ]
|
|
64
|
+
out = @enc.encode(x)
|
|
65
|
+
out.should == "[[]]"
|
|
66
|
+
@dec.decode(out).should == x
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "should handle Array" do
|
|
70
|
+
x = basic_objs.map{|e| e[0]}
|
|
71
|
+
out = @enc.encode(x)
|
|
72
|
+
out.should == "[[null,true,false,1234,1.234,\"symbol\",\"String\"]]"
|
|
73
|
+
y = @dec.decode(out)
|
|
74
|
+
y.should == x.map{|e| Symbol === e ? e.to_s : e }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it "should handle empty Hash" do
|
|
78
|
+
x = { }
|
|
79
|
+
out = @enc.encode(x)
|
|
80
|
+
out.should == "[{}]"
|
|
81
|
+
@dec.decode(out).should == x
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "should handle Hash" do
|
|
85
|
+
x = Hash[ *basic_objs.flatten.reverse ]
|
|
86
|
+
out = @enc.encode(x)
|
|
87
|
+
out.should =~ %r{\A\[\{}
|
|
88
|
+
out.should =~ %r{\}\]\Z}
|
|
89
|
+
basic_objs.each do | v, str |
|
|
90
|
+
# out.should =~ %r{#{k.inspect}:}
|
|
91
|
+
out.should =~ %r{#{str}}
|
|
92
|
+
end
|
|
93
|
+
y = @dec.decode(out)
|
|
94
|
+
y.should == x.inject({}){|h, (k, v)| h[k] = Symbol === v ? v.to_s : v; h }
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
module ASIR::Coder::Test
|
|
98
|
+
class Object
|
|
99
|
+
attr_accessor :a, :h, :o
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it "should handle deep objects" do
|
|
104
|
+
x = ASIR::Coder::Test::Object.new
|
|
105
|
+
x.a = [ *basic_objs.map{|a| a[0]} ]
|
|
106
|
+
x.h = Hash[ *basic_objs.flatten.reverse ]
|
|
107
|
+
x.o = ASIR::Coder::Test::Object.new
|
|
108
|
+
x.o.a = 123
|
|
109
|
+
out = @enc.encode(x)
|
|
110
|
+
# FIXME:
|
|
111
|
+
out.should =~ %r{\A\[\"#<ASIR::Coder::Test::Object:[^>]+>\"\]\Z}
|
|
112
|
+
#out.should =~ %r{<#{x.class.name.gsub('::', '.')} id=\"#{x.object_id}\" >}
|
|
113
|
+
#out.should =~ %r{</#{x.class.name.gsub('::', '.')}>}
|
|
114
|
+
y = @dec.decode(out)
|
|
115
|
+
(String === y).should == true
|
|
116
|
+
=begin
|
|
117
|
+
FIXME:
|
|
118
|
+
y.a.should == x.a
|
|
119
|
+
y.h.should == x.h
|
|
120
|
+
y.o.class.should == ASIR::Coder::Test::Object
|
|
121
|
+
y.o.a.should == x.o.a
|
|
122
|
+
x.instance_variables.sort { | a, b | a.to_s <=> b.to_s }.should ==
|
|
123
|
+
y.instance_variables.sort { | a, b | a.to_s <=> b.to_s }
|
|
124
|
+
=end
|
|
125
|
+
end
|
|
126
|
+
#end
|
|
127
|
+
end
|
|
128
|
+
|