bitgirder-platform 0.1.7
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/LICENSE.txt +176 -0
- data/bin/ensure-test-db +117 -0
- data/bin/install-mysql +375 -0
- data/bin/tomcat7 +569 -0
- data/lib/bitgirder/concurrent.rb +400 -0
- data/lib/bitgirder/core.rb +1235 -0
- data/lib/bitgirder/etl.rb +58 -0
- data/lib/bitgirder/event/file.rb +485 -0
- data/lib/bitgirder/event/logger/testing.rb +140 -0
- data/lib/bitgirder/event/logger.rb +137 -0
- data/lib/bitgirder/event/testing.rb +88 -0
- data/lib/bitgirder/http.rb +255 -0
- data/lib/bitgirder/io/testing.rb +33 -0
- data/lib/bitgirder/io.rb +959 -0
- data/lib/bitgirder/irb.rb +35 -0
- data/lib/bitgirder/mysql.rb +60 -0
- data/lib/bitgirder/ops/java.rb +117 -0
- data/lib/bitgirder/ops/ruby.rb +235 -0
- data/lib/bitgirder/testing.rb +152 -0
- data/lib/doc-gen0.rb +0 -0
- data/lib/doc-gen1.rb +0 -0
- data/lib/doc-gen10.rb +0 -0
- data/lib/doc-gen11.rb +0 -0
- data/lib/doc-gen12.rb +0 -0
- data/lib/doc-gen13.rb +0 -0
- data/lib/doc-gen14.rb +0 -0
- data/lib/doc-gen15.rb +0 -0
- data/lib/doc-gen16.rb +0 -0
- data/lib/doc-gen17.rb +14 -0
- data/lib/doc-gen18.rb +0 -0
- data/lib/doc-gen19.rb +0 -0
- data/lib/doc-gen2.rb +0 -0
- data/lib/doc-gen20.rb +182 -0
- data/lib/doc-gen21.rb +0 -0
- data/lib/doc-gen3.rb +0 -0
- data/lib/doc-gen4.rb +0 -0
- data/lib/doc-gen5.rb +0 -0
- data/lib/doc-gen6.rb +0 -0
- data/lib/doc-gen7.rb +0 -0
- data/lib/doc-gen8.rb +0 -0
- data/lib/doc-gen9.rb +0 -0
- data/lib/mingle/bincodec.rb +512 -0
- data/lib/mingle/codec.rb +54 -0
- data/lib/mingle/http.rb +156 -0
- data/lib/mingle/io/stream.rb +142 -0
- data/lib/mingle/io.rb +160 -0
- data/lib/mingle/json.rb +257 -0
- data/lib/mingle/service.rb +110 -0
- data/lib/mingle-em.rb +92 -0
- data/lib/mingle.rb +2917 -0
- metadata +100 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
require 'bitgirder/core'
|
|
2
|
+
include BitGirder::Core
|
|
3
|
+
|
|
4
|
+
require 'thread'
|
|
5
|
+
require 'set'
|
|
6
|
+
|
|
7
|
+
module BitGirder
|
|
8
|
+
module Event
|
|
9
|
+
|
|
10
|
+
# Base library for BitGirder event logging. Generators of an event will call
|
|
11
|
+
# Engine.log_event, which dispatches the event to a dynamic set of listeners.
|
|
12
|
+
#
|
|
13
|
+
# Typically an application will create a single Engine instance during
|
|
14
|
+
# application startup, register some number of listeners, and then make the
|
|
15
|
+
# engine available to the rest of the application for logging events via
|
|
16
|
+
# Engine#log_event.
|
|
17
|
+
#
|
|
18
|
+
# Listeners registered with an Engine (see Engine#add_listener) should process
|
|
19
|
+
# events immediately and without blocking, since they execute in the call stack
|
|
20
|
+
# of the event producer. In particular, implementations which serialize events
|
|
21
|
+
# and perform IO (write to disk, send over a network) should be careful not to
|
|
22
|
+
# perform the IO directly upon receiving the event, but should delegate this to
|
|
23
|
+
# some ancillary thread.
|
|
24
|
+
#
|
|
25
|
+
# Events can be any ruby object. It is up to each listener to decide if/how to
|
|
26
|
+
# handle a given event.
|
|
27
|
+
#
|
|
28
|
+
# Development roadmap for this library:
|
|
29
|
+
#
|
|
30
|
+
# - Add skeletal listener implementations to simplify offloading IO or other
|
|
31
|
+
# intensive processing to a helper thread, as well as managing queuing
|
|
32
|
+
# policies and overload behavior (drop new events, drop old events, grow
|
|
33
|
+
# unbounded, etc).
|
|
34
|
+
#
|
|
35
|
+
module Logger
|
|
36
|
+
|
|
37
|
+
# An Engine coordinates dispatching of logged events a dynamic set of listeners.
|
|
38
|
+
# All methods are safe to call from concurrent threads.
|
|
39
|
+
class Engine < BitGirderClass
|
|
40
|
+
|
|
41
|
+
bg_attr :error_handler,
|
|
42
|
+
:required => false,
|
|
43
|
+
:description => <<-END_DESC
|
|
44
|
+
If set, this object will be called for various error methods to
|
|
45
|
+
which it responds.
|
|
46
|
+
END_DESC
|
|
47
|
+
|
|
48
|
+
# Creates a new instance with an empty listener set.
|
|
49
|
+
def impl_initialize # :nodoc:
|
|
50
|
+
|
|
51
|
+
super
|
|
52
|
+
|
|
53
|
+
@listeners = Set.new
|
|
54
|
+
@mut = Mutex.new
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# In case we later decide to allow @mut to be optional or of varying
|
|
58
|
+
# implementations (not all apps which log will necessarily be threaded)
|
|
59
|
+
# we'll only need to modify this block to run code which should be
|
|
60
|
+
# threadsafe
|
|
61
|
+
private
|
|
62
|
+
def guarded( &blk )
|
|
63
|
+
@mut.synchronize( &blk )
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Gets the number of listeners managed by this engine
|
|
67
|
+
public
|
|
68
|
+
def listener_count
|
|
69
|
+
guarded { @listeners.size }
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
private
|
|
73
|
+
def listener_failed( l, ev, ex )
|
|
74
|
+
|
|
75
|
+
if @error_handler.respond_to?( :listener_failed )
|
|
76
|
+
@error_handler.listener_failed( l, ev, ex )
|
|
77
|
+
else
|
|
78
|
+
warn( ex, "Listener #{l} failed for event #{ev}" )
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Logs an event. After this method returns all listeners will have received
|
|
83
|
+
# the event.
|
|
84
|
+
public
|
|
85
|
+
def log_event( ev )
|
|
86
|
+
|
|
87
|
+
# Accumulate failures here so we can process them after releasing the
|
|
88
|
+
# lock
|
|
89
|
+
failures = []
|
|
90
|
+
|
|
91
|
+
guarded do
|
|
92
|
+
@listeners.each do |l|
|
|
93
|
+
begin
|
|
94
|
+
l.event_logged( ev )
|
|
95
|
+
rescue Exception => ex
|
|
96
|
+
failures << [ l, ev, ex ]
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
failures.each { |arr| listener_failed( *arr ) }
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Adds the given listener to this engine if it is not already present. All
|
|
105
|
+
# subsequent calls to log_event will dispatch to +l+ until a call is made to
|
|
106
|
+
# remove_listener
|
|
107
|
+
#
|
|
108
|
+
# This method returns +l+ to allow callers to chain listener
|
|
109
|
+
# creation/addition:
|
|
110
|
+
#
|
|
111
|
+
# list = eng.add_listener( SomeListener.new( ... ) )
|
|
112
|
+
#
|
|
113
|
+
public
|
|
114
|
+
def add_listener( l )
|
|
115
|
+
|
|
116
|
+
guarded do
|
|
117
|
+
if l.respond_to?( :event_logged )
|
|
118
|
+
@listeners << l unless @listeners.include?( l )
|
|
119
|
+
else
|
|
120
|
+
raise "Not an event listener: #{l} (#{l.class})"
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
l
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Removes +l+ from the dispatch set. It is not an error to call this
|
|
128
|
+
# method for an unregistered listener.
|
|
129
|
+
public
|
|
130
|
+
def remove_listener( l )
|
|
131
|
+
guarded { @listeners.delete( l ) }
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
require 'bitgirder/core'
|
|
2
|
+
include BitGirder::Core
|
|
3
|
+
|
|
4
|
+
require 'bitgirder/io'
|
|
5
|
+
require 'bitgirder/io/testing'
|
|
6
|
+
include BitGirder::Io
|
|
7
|
+
|
|
8
|
+
module BitGirder
|
|
9
|
+
module Event
|
|
10
|
+
module Testing
|
|
11
|
+
|
|
12
|
+
class Int32Event < BitGirderClass
|
|
13
|
+
|
|
14
|
+
TYPE_CODE = 0x0001
|
|
15
|
+
|
|
16
|
+
bg_attr :i
|
|
17
|
+
|
|
18
|
+
def self.from_i( i ); self.new( :i => i ); end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class BufferEvent < BitGirderClass
|
|
22
|
+
|
|
23
|
+
TYPE_CODE = 0x0002
|
|
24
|
+
|
|
25
|
+
bg_attr :buf
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class DelayEvent < BitGirderClass
|
|
29
|
+
|
|
30
|
+
bg_attr :delay # will be arg to sleep()
|
|
31
|
+
bg_attr :event
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class TestCodec < BitGirderClass
|
|
35
|
+
|
|
36
|
+
include BitGirder::Io
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
def impl_initialize
|
|
40
|
+
@conv = BinaryConverter.new( :order => Io::ORDER_LITTLE_ENDIAN )
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
public
|
|
44
|
+
def encode_event( ev, io )
|
|
45
|
+
|
|
46
|
+
if ev.is_a?( DelayEvent )
|
|
47
|
+
sleep( ev.delay )
|
|
48
|
+
ev = ev.event
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
io.write( @conv.write_int32( ev.class::TYPE_CODE ) )
|
|
52
|
+
|
|
53
|
+
case ev
|
|
54
|
+
when Int32Event then io.write( @conv.write_int32( ev.i ) )
|
|
55
|
+
when BufferEvent then io.write( ev.buf )
|
|
56
|
+
else raise TypeError.new( "Unrecognized event: #{ev.class}" )
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
public
|
|
61
|
+
def decode_event( io, len )
|
|
62
|
+
|
|
63
|
+
ev_buf_len = len - 4
|
|
64
|
+
|
|
65
|
+
case cd = @conv.read_int32( io.read( 4 ) )
|
|
66
|
+
when Int32Event::TYPE_CODE
|
|
67
|
+
Int32Event.from_i( @conv.read_int32( io.read( 4 ) ) )
|
|
68
|
+
when BufferEvent::TYPE_CODE
|
|
69
|
+
BufferEvent.new( Io.read_full( io, ev_buf_len ) )
|
|
70
|
+
else raise sprintf( "Unexpected type code: %04x", cd )
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def self.roundtrip( ev, codec )
|
|
76
|
+
|
|
77
|
+
io = Io::Testing.new_string_io
|
|
78
|
+
codec.encode_event( ev, io )
|
|
79
|
+
|
|
80
|
+
len = io.pos
|
|
81
|
+
io.seek( 0, IO::SEEK_SET )
|
|
82
|
+
|
|
83
|
+
codec.decode_event( io, len )
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
require 'bitgirder/core'
|
|
2
|
+
include BitGirder::Core
|
|
3
|
+
|
|
4
|
+
require 'mingle'
|
|
5
|
+
include Mingle
|
|
6
|
+
|
|
7
|
+
require 'net/http'
|
|
8
|
+
|
|
9
|
+
module BitGirder
|
|
10
|
+
module Http
|
|
11
|
+
|
|
12
|
+
class HttpHeaders < BitGirderClass
|
|
13
|
+
|
|
14
|
+
private_class_method :new
|
|
15
|
+
|
|
16
|
+
bg_attr :pairs,
|
|
17
|
+
:default => [],
|
|
18
|
+
:processor => lambda { |pairs| pairs.sort!.freeze }
|
|
19
|
+
|
|
20
|
+
def self.as_header_name( nm )
|
|
21
|
+
nm.to_s.downcase
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.as_header_val( val )
|
|
25
|
+
val.to_s.strip
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.as_header_val_list( val )
|
|
29
|
+
|
|
30
|
+
case val
|
|
31
|
+
|
|
32
|
+
when Array, MingleList
|
|
33
|
+
val.empty? ? [ "" ] : val.map { |v| self.as_header_val( v ) }
|
|
34
|
+
|
|
35
|
+
else [ self.as_header_val( val ) ]
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
map_instance_of( Hash ) do |h|
|
|
40
|
+
|
|
41
|
+
pairs = {}
|
|
42
|
+
|
|
43
|
+
h.each_pair do |k, v|
|
|
44
|
+
arr = ( pairs[ self.as_header_name( k ) ] ||= [] )
|
|
45
|
+
arr.push( *( self.as_header_val_list( v ) ) )
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
self.send( :new, :pairs => pairs.to_a )
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
map_instance_of( Array ) do |arr|
|
|
52
|
+
|
|
53
|
+
pairs = arr.map do |pair|
|
|
54
|
+
|
|
55
|
+
if pair.size == 2
|
|
56
|
+
[ self.as_header_name( pair[ 0 ] ),
|
|
57
|
+
self.as_header_val_list( pair[ 1 ] ) ]
|
|
58
|
+
else
|
|
59
|
+
raise "Not a http header pair: #{pair.inspect}"
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
self.send( :new, :pairs => pairs )
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
map_instance_of( Net::HTTPHeader ) do |hdrs|
|
|
67
|
+
|
|
68
|
+
pairs = []
|
|
69
|
+
hdrs.each_name { |nm| pairs << [ nm.downcase, hdrs.get_fields( nm ) ] }
|
|
70
|
+
|
|
71
|
+
self.send( :new, :pairs => pairs )
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
public
|
|
75
|
+
def to_mingle_struct
|
|
76
|
+
|
|
77
|
+
MingleStruct.new(
|
|
78
|
+
:type => :"bitgirder:http@v1/HttpHeaders",
|
|
79
|
+
:fields => { :pairs => @pairs.map { |p| MingleList.new( p ) } }
|
|
80
|
+
)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def self.from_mingle_struct( ms )
|
|
84
|
+
self.as_instance( ( ms[ :pairs ] || [] ).to_a )
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
class HttpEndpoint < BitGirderClass
|
|
89
|
+
|
|
90
|
+
bg_attr :host, :required => false
|
|
91
|
+
bg_attr :port, :required => false
|
|
92
|
+
bg_attr :is_ssl, :required => false
|
|
93
|
+
|
|
94
|
+
map_instance_of( Net::HTTP ) do |http|
|
|
95
|
+
|
|
96
|
+
new(
|
|
97
|
+
:host => http.address,
|
|
98
|
+
:port => http.port,
|
|
99
|
+
:is_ssl => http.use_ssl?
|
|
100
|
+
)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def to_mingle_struct
|
|
104
|
+
|
|
105
|
+
MingleStruct.new(
|
|
106
|
+
:type => :"bitgirder:http@v1/HttpEndpoint",
|
|
107
|
+
:fields => {
|
|
108
|
+
:host => @host,
|
|
109
|
+
:port => @port,
|
|
110
|
+
:is_ssl => @is_ssl
|
|
111
|
+
}
|
|
112
|
+
)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def self.from_mingle_struct( ms )
|
|
116
|
+
|
|
117
|
+
self.new(
|
|
118
|
+
:host => ms.fields.get_string( :host ),
|
|
119
|
+
:port => ms.fields.get_int( :port ),
|
|
120
|
+
:is_ssl => ms.fields.get_boolean( :is_ssl )
|
|
121
|
+
)
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
PROC_TO_BIN = lambda { |b|
|
|
126
|
+
RubyVersions.when_19x( b ) { b.encode( Encoding::BINARY ) }
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
class HttpRequest < BitGirderClass
|
|
130
|
+
|
|
131
|
+
bg_attr :headers, :processor => HttpHeaders, :required => false
|
|
132
|
+
bg_attr :path, :required => false
|
|
133
|
+
bg_attr :body, :processor => PROC_TO_BIN, :required => false
|
|
134
|
+
|
|
135
|
+
def to_mingle_struct
|
|
136
|
+
|
|
137
|
+
MingleStruct.new(
|
|
138
|
+
:type => :"bitgirder:http@v1/HttpRequest",
|
|
139
|
+
:fields => {
|
|
140
|
+
:headers => @headers ? @headers.to_mingle_struct : nil,
|
|
141
|
+
:path => @path,
|
|
142
|
+
:body => @body ? MingleBuffer.new( @body ) : nil
|
|
143
|
+
}
|
|
144
|
+
)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def self.from_mingle_struct( ms )
|
|
148
|
+
|
|
149
|
+
mg_hdrs, mg_body = ms[ :headers ], ms[ :body ]
|
|
150
|
+
|
|
151
|
+
self.new(
|
|
152
|
+
:headers =>
|
|
153
|
+
mg_hdrs ? HttpHeaders.from_mingle_struct( mg_hdrs ) : nil,
|
|
154
|
+
:path => ms.fields.get_string( :path ),
|
|
155
|
+
:body => mg_body ? mg_body.buf : nil
|
|
156
|
+
)
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
class HttpStatus < BitGirderClass
|
|
161
|
+
|
|
162
|
+
bg_attr :code
|
|
163
|
+
bg_attr :message
|
|
164
|
+
bg_attr :version
|
|
165
|
+
|
|
166
|
+
map_instance_of( Net::HTTPResponse ) do |resp|
|
|
167
|
+
|
|
168
|
+
ver =
|
|
169
|
+
if ( ver_base = resp.http_version ).start_with?( "HTTP/" )
|
|
170
|
+
ver_base
|
|
171
|
+
else
|
|
172
|
+
"HTTP/#{ver_base}"
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
self.new(
|
|
176
|
+
:message => resp.message, :code => resp.code, :version => ver )
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
public
|
|
180
|
+
def to_mingle_struct
|
|
181
|
+
MingleStruct.new(
|
|
182
|
+
:type => :"bitgirder:http@v1/HttpStatus",
|
|
183
|
+
:fields => {
|
|
184
|
+
:code => @code,
|
|
185
|
+
:message => @message,
|
|
186
|
+
:version => @version
|
|
187
|
+
}
|
|
188
|
+
)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def self.from_mingle_struct( ms )
|
|
192
|
+
|
|
193
|
+
self.new(
|
|
194
|
+
:code => ms[ :code ].to_i,
|
|
195
|
+
:message => ms[ :message ].to_s,
|
|
196
|
+
:version => ms[ :version ].to_s
|
|
197
|
+
)
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
class HttpResponse < BitGirderClass
|
|
202
|
+
|
|
203
|
+
bg_attr :status, :processor => HttpStatus, :required => false
|
|
204
|
+
bg_attr :headers, :processor => HttpHeaders, :required => false
|
|
205
|
+
bg_attr :body, :processor => PROC_TO_BIN, :required => false
|
|
206
|
+
|
|
207
|
+
def self.from_net_http_response( resp, opts = {} )
|
|
208
|
+
|
|
209
|
+
not_nil( resp, :resp )
|
|
210
|
+
not_nil( opts, :opts )
|
|
211
|
+
|
|
212
|
+
log_body = opts[ :log_body ]
|
|
213
|
+
|
|
214
|
+
attrs = {
|
|
215
|
+
:status => HttpStatus.as_instance( resp ),
|
|
216
|
+
:headers => HttpHeaders.as_instance( resp )
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if opts[ :log_body ] && resp.class.body_permitted?
|
|
220
|
+
attrs[ :body ] = resp.body
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
new( attrs )
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
map_instance_of( Net::HTTPResponse ) do |resp|
|
|
227
|
+
self.from_net_http_response( resp, :log_body => false )
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def to_mingle_struct
|
|
231
|
+
|
|
232
|
+
MingleStruct.new(
|
|
233
|
+
:type => :"bitgirder:http@v1/HttpResponse",
|
|
234
|
+
:fields => {
|
|
235
|
+
:status => @status ? @status.to_mingle_struct : nil,
|
|
236
|
+
:headers => @headers ? @headers.to_mingle_struct : nil,
|
|
237
|
+
:body => @body ? MingleBuffer.new( body ) : nil
|
|
238
|
+
}
|
|
239
|
+
)
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def self.from_mingle_struct( ms )
|
|
243
|
+
|
|
244
|
+
stat, hdrs, body = ms[ :status ], ms[ :headers ], ms[ :body ]
|
|
245
|
+
|
|
246
|
+
self.new(
|
|
247
|
+
:status => stat ? HttpStatus.from_mingle_struct( stat ) : nil,
|
|
248
|
+
:headers => hdrs ? HttpHeaders.from_mingle_struct( hdrs ) : nil,
|
|
249
|
+
:body => body ? body.buf : nil
|
|
250
|
+
)
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
end
|
|
255
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'bitgirder/core'
|
|
2
|
+
require 'stringio'
|
|
3
|
+
|
|
4
|
+
module BitGirder
|
|
5
|
+
module Io
|
|
6
|
+
|
|
7
|
+
module Testing
|
|
8
|
+
|
|
9
|
+
[ :force_encoding, :encode, :encode! ].each do |meth|
|
|
10
|
+
define_method( :"opt_#{meth}" ) do |s, *argv|
|
|
11
|
+
RubyVersions.when_19x( s ) { |s| s.send( meth, *argv ) }
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def new_string_io( str = "" )
|
|
16
|
+
RubyVersions.when_19x( StringIO.new( str ) ) do |io|
|
|
17
|
+
io.set_encoding( "binary" )
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
module_function :new_string_io
|
|
22
|
+
|
|
23
|
+
def rand_buf( len )
|
|
24
|
+
|
|
25
|
+
len = len.bytes if len.is_a?( DataSize )
|
|
26
|
+
File.open( "/dev/random", "rb" ) { |io| Io.read_full( io, len ) }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
module_function :rand_buf
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
33
|
+
end
|