plezi 0.11.2 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/README.md +32 -33
- data/docs/async_helpers.md +90 -40
- data/docs/logging.md +38 -3
- data/docs/routes.md +177 -5
- data/docs/websockets.md +5 -0
- data/lib/plezi.rb +2 -10
- data/lib/plezi/common/api.rb +48 -101
- data/lib/plezi/common/defer.rb +4 -4
- data/lib/plezi/common/dsl.rb +13 -24
- data/lib/plezi/common/redis.rb +9 -5
- data/lib/plezi/common/settings.rb +4 -24
- data/lib/plezi/handlers/controller_core.rb +7 -14
- data/lib/plezi/handlers/controller_magic.rb +12 -10
- data/lib/plezi/handlers/http_router.rb +27 -22
- data/lib/plezi/handlers/placebo.rb +40 -33
- data/lib/plezi/handlers/route.rb +233 -234
- data/lib/plezi/handlers/session.rb +2 -2
- data/lib/plezi/handlers/stubs.rb +7 -0
- data/lib/plezi/handlers/ws_object.rb +25 -15
- data/lib/plezi/helpers/http_sender.rb +3 -3
- data/lib/plezi/helpers/magic_helpers.rb +3 -3
- data/lib/plezi/version.rb +1 -1
- data/plezi.gemspec +1 -1
- data/resources/config.ru +12 -18
- data/resources/environment.rb +6 -7
- data/resources/mini_app.rb +22 -22
- data/resources/redis_config.rb +4 -2
- data/test/plezi_tests.rb +76 -87
- data/websocket chatroom.md +3 -5
- metadata +6 -6
- data/docs/http_helpers.md +0 -9
@@ -5,7 +5,7 @@ module Plezi
|
|
5
5
|
# returns a session object
|
6
6
|
def fetch id
|
7
7
|
return Plezi::Session.new(id) if Plezi.redis # avoid a local cache if Redis is used.
|
8
|
-
|
8
|
+
Iodine::Http::SessionManager::FileSessionStorage.fetch id # use the tmp-file-session logic if Redis isn't present
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
@@ -90,5 +90,5 @@ module Plezi
|
|
90
90
|
|
91
91
|
end
|
92
92
|
end
|
93
|
-
|
93
|
+
Iodine::Http::SessionManager.storage = Plezi::Base::SessionStorage
|
94
94
|
end
|
data/lib/plezi/handlers/stubs.rb
CHANGED
@@ -120,6 +120,13 @@ module Plezi
|
|
120
120
|
response << data.to_s
|
121
121
|
end
|
122
122
|
|
123
|
+
# a CLASS level callback that will be called when a unicast doesn't find it's target.
|
124
|
+
#
|
125
|
+
# the lack of this callback being called does NOT imply that the unicast was processed without errors,
|
126
|
+
# it's only called if the target itself wasn't found.
|
127
|
+
def self.failed_unicast target, method, arguments_array
|
128
|
+
end
|
129
|
+
|
123
130
|
#####
|
124
131
|
## It is possible to use RESTful methods to help emulate long XHR pulling.
|
125
132
|
## a RESTful controller can also be a WebSockets controller (these are not exclusive qualities).
|
@@ -27,10 +27,9 @@ module Plezi
|
|
27
27
|
module InstanceMethods
|
28
28
|
public
|
29
29
|
# handles broadcasts / unicasts
|
30
|
-
def on_broadcast
|
31
|
-
data
|
32
|
-
|
33
|
-
GReactor.warn "Broadcast message unknown... falling back on base broadcasting"
|
30
|
+
def on_broadcast data
|
31
|
+
unless data.is_a?(Hash) && (data[:type] || data[:target]) && data[:method] && data[:data]
|
32
|
+
Iodine.warn "Broadcast message unknown... falling back on base broadcasting"
|
34
33
|
return super(data) if defined? super
|
35
34
|
return false
|
36
35
|
end
|
@@ -73,12 +72,10 @@ module Plezi
|
|
73
72
|
#
|
74
73
|
# This UUID is also used to make sure Radis broadcasts don't triger the
|
75
74
|
# boadcasting object's event.
|
76
|
-
def uuid
|
75
|
+
def uuid
|
77
76
|
return @uuid if @uuid
|
78
|
-
if
|
79
|
-
return (@uuid ||=
|
80
|
-
elsif @io
|
81
|
-
return (@uuid ||= (@io[:uuid] ||= SecureRandom.uuid) + Plezi::Settings.uuid)
|
77
|
+
if __get_io
|
78
|
+
return (@uuid ||= Plezi::Settings.uuid + @io.id)
|
82
79
|
end
|
83
80
|
nil
|
84
81
|
end
|
@@ -86,7 +83,7 @@ module Plezi
|
|
86
83
|
|
87
84
|
protected
|
88
85
|
def __get_io
|
89
|
-
@io ||= (@request ? @request
|
86
|
+
@io ||= (@request ? @request[:io] : nil)
|
90
87
|
end
|
91
88
|
end
|
92
89
|
module ClassMethods
|
@@ -111,6 +108,7 @@ module Plezi
|
|
111
108
|
@exposed_methods_list ||= ( (self.public_instance_methods - Class.new.instance_methods - Plezi::ControllerMagic::InstanceMethods.instance_methods - [:before, :after, :save, :show, :update, :delete, :initialize, :on_message, :on_broadcast, :pre_connect, :on_open, :on_close]).delete_if {|m| m.to_s[0] == '_'} ).to_set
|
112
109
|
@exposed_methods_list.include? method_name
|
113
110
|
end
|
111
|
+
|
114
112
|
protected
|
115
113
|
|
116
114
|
# a callback that resets the class router whenever a method (a potential route) is added
|
@@ -163,7 +161,7 @@ module Plezi
|
|
163
161
|
def unicast target_uuid, method_name, *args
|
164
162
|
raise 'No target specified for unicasting!' unless target_uuid
|
165
163
|
@@uuid_cutoff ||= Plezi::Settings.uuid.length
|
166
|
-
_inner_broadcast method: method_name, data: args, target: target_uuid[
|
164
|
+
_inner_broadcast method: method_name, data: args, target: target_uuid[@@uuid_cutoff..-1], to_server: target_uuid[0...@@uuid_cutoff], type: self
|
167
165
|
end
|
168
166
|
|
169
167
|
# Use this to multicast an event to ALL websocket connections on EVERY controller, including Placebo controllers.
|
@@ -183,9 +181,12 @@ module Plezi
|
|
183
181
|
# sends the broadcast
|
184
182
|
def _inner_broadcast data, ignore_io = nil
|
185
183
|
if data[:target]
|
186
|
-
|
184
|
+
if data[:target] && (data[:to_server] == Plezi::Settings.uuid )
|
185
|
+
return ( ::Iodine::Http::Websockets.unicast( data[:target], data ) || ___faild_unicast( data ) )
|
186
|
+
end
|
187
|
+
return ( data[:to_server].nil? && ::Iodine::Http::Websockets.unicast(data[:target], data) ) || ( Plezi::Base::AutoRedis.away?(data[:to_server]) && ___faild_unicast( data ) ) || __inner_redis_broadcast(data)
|
187
188
|
else
|
188
|
-
|
189
|
+
::Iodine::Http::Websockets.broadcast data, ignore_io
|
189
190
|
__inner_redis_broadcast data
|
190
191
|
end
|
191
192
|
true
|
@@ -194,16 +195,25 @@ module Plezi
|
|
194
195
|
def __inner_redis_broadcast data
|
195
196
|
return unless conn = Plezi.redis
|
196
197
|
data = data.dup
|
197
|
-
data[:type] = data[:type].name if data[:type]
|
198
|
+
data[:type] = data[:type].name if data[:type].is_a?(Class)
|
198
199
|
data[:server] = Plezi::Settings.uuid
|
199
|
-
return conn.publish( ( data[:to_server]
|
200
|
+
return conn.publish( ( data[:to_server] || Plezi::Settings.redis_channel_name ), data.to_yaml ) if conn
|
200
201
|
false
|
201
202
|
end
|
202
203
|
|
204
|
+
def ___faild_unicast data
|
205
|
+
has_class_method?(:failed_unicast) && failed_unicast( data[:to_server].to_s + data[:target], data[:method], data[:data] )
|
206
|
+
true
|
207
|
+
end
|
208
|
+
|
203
209
|
def has_method? method_name
|
204
210
|
@methods_list ||= self.instance_methods.to_set
|
205
211
|
@methods_list.include? method_name
|
206
212
|
end
|
213
|
+
def has_class_method? method_name
|
214
|
+
@class_methods_list ||= self.methods.to_set - Object.methods
|
215
|
+
@class_methods_list.include? method_name
|
216
|
+
end
|
207
217
|
end
|
208
218
|
end
|
209
219
|
end
|
@@ -18,7 +18,7 @@ module Plezi
|
|
18
18
|
# sends a response for an error code, rendering the relevent file (if exists).
|
19
19
|
def send_by_code request, response, code, headers = {}
|
20
20
|
begin
|
21
|
-
base_code_path = request
|
21
|
+
base_code_path = request[:host_settings][:templates] || File.expand_path('.')
|
22
22
|
fn = File.join(base_code_path, "#{code}.html")
|
23
23
|
rendered = ::Plezi::Renderer.render fn, binding #CodeContext.new(request)
|
24
24
|
return send_raw_data request, response, rendered, 'text/html', code, headers if rendered
|
@@ -34,14 +34,14 @@ module Plezi
|
|
34
34
|
#
|
35
35
|
# returns true if data was sent.
|
36
36
|
def send_static_file request, response
|
37
|
-
root = request
|
37
|
+
root = request[:host_settings][:public]
|
38
38
|
return false unless root
|
39
39
|
file_requested = request[:path].to_s.split('/')
|
40
40
|
unless file_requested.include? '..'
|
41
41
|
file_requested.shift
|
42
42
|
file_requested = File.join(root, *file_requested)
|
43
43
|
return true if send_file request, response, file_requested
|
44
|
-
return send_file request, response, File.join(file_requested, request
|
44
|
+
return send_file request, response, File.join(file_requested, request[:host_settings][:index_file])
|
45
45
|
end
|
46
46
|
false
|
47
47
|
end
|
@@ -32,7 +32,7 @@ module Plezi
|
|
32
32
|
(str.to_s.gsub(/[^a-z0-9\*\.\_\-]/i) {|m| '%%%02x'.freeze % m.ord }).force_encoding(::Encoding::ASCII_8BIT)
|
33
33
|
end
|
34
34
|
|
35
|
-
# Adds paramaters to a Hash object, according to the
|
35
|
+
# Adds paramaters to a Hash object, according to the Iodine's server conventions.
|
36
36
|
def self.add_param_to_hash name, value, target
|
37
37
|
begin
|
38
38
|
c = target
|
@@ -64,8 +64,8 @@ module Plezi
|
|
64
64
|
end
|
65
65
|
val
|
66
66
|
rescue => e
|
67
|
-
|
68
|
-
|
67
|
+
Iodine.error e
|
68
|
+
Iodine.error "(Silent): parameters parse error for #{name} ... maybe conflicts with a different set?"
|
69
69
|
target[name] = val
|
70
70
|
end
|
71
71
|
end
|
data/lib/plezi/version.rb
CHANGED
data/plezi.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_dependency "
|
21
|
+
spec.add_dependency "iodine", "~> 0.1.0"
|
22
22
|
spec.add_development_dependency "bundler", "~> 1.7"
|
23
23
|
spec.add_development_dependency "rake", "~> 10.0"
|
24
24
|
|
data/resources/config.ru
CHANGED
@@ -3,14 +3,11 @@
|
|
3
3
|
#
|
4
4
|
# using Rack with Plezi poses some limitations...:
|
5
5
|
#
|
6
|
-
# 1.
|
7
|
-
# (only the first `listen` call and all it's related `host` calls)
|
6
|
+
# 1. there is NO WebSockets support for Rack apps.
|
8
7
|
#
|
9
|
-
# 2.
|
8
|
+
# 2. this might break any streaming / asynchronous methods calls, such as Iodine's Http streaming.
|
10
9
|
#
|
11
|
-
# 3.
|
12
|
-
#
|
13
|
-
# 4. Plezi parameters and file uploads are different then Rack - HTML Form code might be incompatible!
|
10
|
+
# 3. Plezi parameters and file uploads are different then Rack - HTML Form code might be incompatible!
|
14
11
|
# This MIGHT BREAKE YOUR CODE! (changing this requires Plezi to re-parse the HTML, and costs in performance).
|
15
12
|
#
|
16
13
|
# also, all Plezi server specific configuration will be ignored.
|
@@ -21,8 +18,12 @@
|
|
21
18
|
#
|
22
19
|
# 2. you have better control over Middleware then you could have with Plezi.
|
23
20
|
# ("wait", you might say, "there is no Middleware in Plezi!"... "Ahhh", I will answer, "so much to discover...")
|
24
|
-
|
25
|
-
|
21
|
+
#
|
22
|
+
#
|
23
|
+
##############
|
24
|
+
#
|
25
|
+
# For now, Rack mode is NOT supported unless using the Iodine Http server,
|
26
|
+
# even than you're 404 not found pages will break unless using a catch-all route.
|
26
27
|
|
27
28
|
# load all framework and gems
|
28
29
|
load ::File.expand_path(File.join("..", "environment.rb"), __FILE__)
|
@@ -31,15 +32,8 @@ load ::File.expand_path(File.join("..", "environment.rb"), __FILE__)
|
|
31
32
|
load ::File.expand_path(File.join("..", "routes.rb"), __FILE__)
|
32
33
|
|
33
34
|
# start the plezi EM, to make sure that the plezi async code doesn't break.
|
34
|
-
if Rack::Handler.default ==
|
35
|
-
run(Proc.new { [404, {}, []] })
|
35
|
+
if Rack::Handler.default == Iodine::Http::Rack
|
36
|
+
run(Proc.new { [404, {}, ["not found"]] })
|
36
37
|
else
|
37
|
-
|
38
|
-
GReactor.start Plezi::Settings.max_threads
|
39
|
-
|
40
|
-
# run the Rack app - not yet supported
|
41
|
-
# run Plezi::Base::Rack
|
42
|
-
|
43
|
-
# # exit rack to start the plezi server
|
44
|
-
# Process.kill 'TERM'
|
38
|
+
raise "Unsupported Server - Plezi only runs using Iodine."
|
45
39
|
end
|
data/resources/environment.rb
CHANGED
@@ -24,13 +24,13 @@ Bundler.require(:default, ENV['ENV'].to_s.to_sym)
|
|
24
24
|
require 'tilt/sass' if defined?(::Slim) && defined?(::Sass)
|
25
25
|
|
26
26
|
# set up Plezi's logs - Heroku logs to STDOUT, this machine logs to log file
|
27
|
-
|
27
|
+
Iodine.logger = Logger.new(File.expand_path(File.join 'logs','server.log'))
|
28
28
|
|
29
29
|
# set the session token name
|
30
|
-
|
30
|
+
Iodine::Http.session_token = 'appname_uui'
|
31
31
|
|
32
32
|
## Allow forking? ONLY if your code is fully scalable across processes.
|
33
|
-
#
|
33
|
+
# Iodine.processes = 4
|
34
34
|
|
35
35
|
# load all config files
|
36
36
|
Dir[File.join "{config}", "**" , "*.rb"].each {|file| load File.expand_path(file)}
|
@@ -41,10 +41,9 @@ Dir[File.join "{lib}", "**" , "*.rb"].each {|file| load File.expand_path(file)}
|
|
41
41
|
# load all application files
|
42
42
|
Dir[File.join "{app}", "**" , "*.rb"].each {|file| load File.expand_path(file)}
|
43
43
|
|
44
|
-
#
|
45
|
-
|
46
|
-
|
44
|
+
# change some of the default settings here.
|
45
|
+
host :default,
|
46
|
+
public: Root.join('public').to_s,
|
47
47
|
assets: Root.join('assets').to_s,
|
48
48
|
assets_public: '/assets',
|
49
49
|
templates: Root.join('app','views').to_s,
|
50
|
-
ssl: false
|
data/resources/mini_app.rb
CHANGED
@@ -5,14 +5,12 @@
|
|
5
5
|
require 'pathname'
|
6
6
|
## Set up root object, it might be used by the environment and\or the plezi extension gems.
|
7
7
|
Root ||= Pathname.new(File.dirname(__FILE__)).expand_path
|
8
|
-
|
8
|
+
|
9
9
|
## If this app is independant, use bundler to load gems (including the plezi gem).
|
10
|
-
##
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
# Plesi.start_rack # remember
|
15
|
-
GRHttp.session_token = 'appname_uui'
|
10
|
+
## otherwise, use the original app's Gemfile and start Plezi's Rack mode.
|
11
|
+
require 'bundler'
|
12
|
+
Bundler.require(:default, ENV['ENV'].to_s.to_sym)
|
13
|
+
|
16
14
|
## make sure all file access and file loading is relative to the application's root folder
|
17
15
|
# Dir.chdir Root.to_s
|
18
16
|
## load code from a subfolder called 'app'
|
@@ -21,14 +19,18 @@
|
|
21
19
|
# Dir[File.join File.dirname(__FILE__), "*.rb"].each {|file| load File.expand_path(file) unless file == __FILE__}
|
22
20
|
|
23
21
|
## Uncomment to create a log file
|
24
|
-
#
|
22
|
+
# Iodine.logger = Logger.new File.expand_path(Root.join('server.log').to_s)
|
25
23
|
|
26
|
-
|
27
|
-
|
28
|
-
#
|
29
|
-
|
24
|
+
# # Options for Scaling the app (across processes or machines):
|
25
|
+
# # uncomment to set up forking for 3 more processes (total of 4).
|
26
|
+
# Iodine.processes = 4
|
27
|
+
#
|
28
|
+
# # Redis scaling
|
30
29
|
# Plezi::Settings.redis_channel_name = 'appsecret'
|
31
30
|
# ENV['PL_REDIS_URL'] ||= ENV['REDIS_URL'] || ENV['REDISCLOUD_URL'] || ENV['REDISTOGO_URL'] || "redis://username:password@my.host:6389"
|
31
|
+
#
|
32
|
+
# # Consider setting a common session token for Redis supported sessions.
|
33
|
+
# Iodine::Http.session_token = 'appname_uui'
|
32
34
|
|
33
35
|
|
34
36
|
# The basic appname controller, to get you started
|
@@ -60,19 +62,17 @@ class MyController
|
|
60
62
|
end
|
61
63
|
|
62
64
|
|
63
|
-
#
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
# public: Root.join('public').to_s,
|
69
|
-
ssl: false
|
65
|
+
# change some of the default settings here.
|
66
|
+
host :default,
|
67
|
+
# public: Root.join('public').to_s,
|
68
|
+
assets: Root.join('assets').to_s,
|
69
|
+
templates: Root.join('templates').to_s
|
70
70
|
|
71
|
-
|
72
|
-
|
71
|
+
# # Optional stuff:
|
72
|
+
# # I18n re-write, i.e.: `/en/home` will be rewriten as `/home`, while setting params[:locale] to "en"
|
73
73
|
# route "/:locale{#{I18n.available_locales.join "|"}}/*" , false if defined? I18n
|
74
74
|
#
|
75
|
-
|
75
|
+
# # OAuth2 - Facebook / Google authentication
|
76
76
|
# require 'plezi/oauth'
|
77
77
|
# ENV["FB_APP_ID"] ||= "app id"; ENV["FB_APP_SECRET"] ||= "secret"; ENV['GOOGLE_APP_ID'] = "app id"; ENV['GOOGLE_APP_SECRET'] = "secret"
|
78
78
|
# create_auth_shared_route do |service_name, auth_token, remote_user_id, remote_user_email, remote_response|
|
data/resources/redis_config.rb
CHANGED
@@ -10,9 +10,11 @@ if defined? Redis
|
|
10
10
|
# ## Sets up Plezi to use Radis broadcast.
|
11
11
|
# ##
|
12
12
|
# ## If Plezi Redis Automation is enabled:
|
13
|
-
# ## Plezi creates is own listening thread for each Controller class that broadcasts using Redis.
|
13
|
+
# ## Plezi creates is own listening thread that listens for each Controller class that broadcasts using Redis.
|
14
14
|
# ## (using the Controller.redis_connection and Controller.redis_channel_name class methods)
|
15
15
|
# ##
|
16
|
+
# ## Only one thread will be created and initiated during startup (dynamically created controller routes might be ignored).
|
17
|
+
# ##
|
16
18
|
# ## this overrides the default Controller#broadcast method which is very powerful but
|
17
19
|
# ## is limited to one process.
|
18
20
|
# ##
|
@@ -33,7 +35,7 @@ if defined? Redis
|
|
33
35
|
# on.message do |channel, msg|
|
34
36
|
# msg = JSON.parse(msg)
|
35
37
|
# # do stuff, i.e.:
|
36
|
-
# # Plezi.
|
38
|
+
# # Plezi.run(msg) { |m| Plezi.info m.to_s }
|
37
39
|
# end
|
38
40
|
# end
|
39
41
|
# end
|
data/test/plezi_tests.rb
CHANGED
@@ -103,6 +103,11 @@ class TestCtrl
|
|
103
103
|
############
|
104
104
|
## WebSockets
|
105
105
|
|
106
|
+
def fail_unicast
|
107
|
+
unicast (params[:uuid] || (Plezi::Settings.uuid + SecureRandom.hex(12))), :psedo, "agrument1"
|
108
|
+
"Sent a psedo unicast... It should fail."
|
109
|
+
end
|
110
|
+
|
106
111
|
# called once the websocket was connected
|
107
112
|
def on_open
|
108
113
|
response << "connected"
|
@@ -116,7 +121,7 @@ class TestCtrl
|
|
116
121
|
when 'get uuid'
|
117
122
|
response << "uuid: #{uuid}"
|
118
123
|
when /to: ([^\s]*)/
|
119
|
-
# puts "
|
124
|
+
# puts "unicasting to target: #{data.match(/to: ([^\s]*)/)[1]}"
|
120
125
|
unicast data.match(/to: ([^\s]*)/)[1], :_push, "unicast"
|
121
126
|
# broadcast :_push, "unicast"
|
122
127
|
else
|
@@ -131,6 +136,10 @@ class TestCtrl
|
|
131
136
|
def on_close
|
132
137
|
end
|
133
138
|
|
139
|
+
def self.failed_unicast target, method, args
|
140
|
+
puts "#{Process.pid}: Failed Unicast, on purpose, for target: #{target}, method: #{method} with: #{args}"
|
141
|
+
end
|
142
|
+
|
134
143
|
# a demo event method that recieves a broadcast from instance siblings.
|
135
144
|
def _push data
|
136
145
|
response << data.to_s
|
@@ -160,7 +169,7 @@ module PleziTestTasks
|
|
160
169
|
true
|
161
170
|
end
|
162
171
|
def test_sleep
|
163
|
-
Plezi.
|
172
|
+
Plezi.run do
|
164
173
|
begin
|
165
174
|
puts " * Sleeper test: #{RESULTS[URI.parse("http://localhost:3000/sleeper").read == 'slept']}"
|
166
175
|
puts " * ASync tasks test: #{RESULTS[true]}"
|
@@ -179,16 +188,18 @@ module PleziTestTasks
|
|
179
188
|
puts e
|
180
189
|
end
|
181
190
|
end
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
191
|
+
# # Starting with Iodine, Plezi can listen only to one port at a time, either SSL or NOT.
|
192
|
+
# def test_ssl
|
193
|
+
# puts " * Connection to non-ssl and unique route test: #{RESULTS[URI.parse("http://localhost:3000/ssl").read == 'false']}"
|
194
|
+
# uri = URI.parse("https://localhost:3030/ssl")
|
195
|
+
# Net::HTTP.start(uri.host, uri.port, use_ssl: (uri.scheme == "https"), verify_mode: OpenSSL::SSL::VERIFY_NONE) do |http|
|
196
|
+
# puts " * Connection to ssl and unique ssl route test: #{RESULTS[ http.request(Net::HTTP::Get.new(uri)).body == 'true' ]}"
|
197
|
+
# end
|
198
|
+
# rescue => e
|
199
|
+
# puts " **** SSL Tests FAILED to complete!!!"
|
200
|
+
# puts e
|
201
|
+
# end
|
202
|
+
|
192
203
|
def test_new
|
193
204
|
puts " * New RESTful path test: #{RESULTS[URI.parse("http://localhost:3000/new").read == 'new']}"
|
194
205
|
|
@@ -244,7 +255,7 @@ module PleziTestTasks
|
|
244
255
|
end
|
245
256
|
def test_placebo
|
246
257
|
puts " * Starting placebo tests..."
|
247
|
-
ws =
|
258
|
+
ws = Iodine::Http::WebsocketClient.connect("ws://localhost:3000/ws/placebo") {|ws| 'ME?'}
|
248
259
|
ws << " * Placebo WS connected."
|
249
260
|
sleep 2
|
250
261
|
ws.close
|
@@ -255,54 +266,53 @@ module PleziTestTasks
|
|
255
266
|
def test_websocket
|
256
267
|
connection_test = broadcast_test = echo_test = unicast_test = false
|
257
268
|
begin
|
258
|
-
ws4 =
|
259
|
-
if
|
269
|
+
ws4 = Iodine::Http::WebsocketClient.connect("ws://localhost:3000") do |data|
|
270
|
+
if data == "unicast"
|
260
271
|
puts " * Websocket unicast testing: #{RESULTS[false]}"
|
261
272
|
unicast_test = :failed
|
262
273
|
end
|
263
274
|
end
|
264
|
-
ws2 =
|
265
|
-
next unless @is_connected || !(@is_connected = true)
|
266
|
-
if
|
275
|
+
ws2 = Iodine::Http::WebsocketClient.connect("ws://localhost:3000") do |data|
|
276
|
+
next unless @is_connected || !( (@is_connected = true) )
|
277
|
+
if data == "unicast"
|
267
278
|
puts " * Websocket unicast message test: #{RESULTS[false]}"
|
268
279
|
unicast_test = :failed
|
269
280
|
next
|
270
281
|
else
|
271
|
-
puts " * Websocket broadcast message test: #{RESULTS[broadcast_test = (
|
282
|
+
puts " * Websocket broadcast message test: #{RESULTS[broadcast_test = (data == 'echo test')]}"
|
272
283
|
go_test = false
|
273
284
|
end
|
274
285
|
end
|
275
|
-
ws3 =
|
276
|
-
if
|
277
|
-
ws2 << "to: #{
|
278
|
-
puts " * Websocket UUID for unicast testing: #{
|
279
|
-
elsif
|
286
|
+
ws3 = Iodine::Http::WebsocketClient.connect("ws://localhost:3000", on_open: -> { write 'get uuid' } ) do |data|
|
287
|
+
if data.match /uuid: ([^s]*)/
|
288
|
+
ws2 << "to: #{data.match(/^uuid: ([^s]*)/)[1]}"
|
289
|
+
puts " * Websocket UUID for unicast testing: #{data.match(/^uuid: ([^s]*)/)[1]}"
|
290
|
+
elsif data == "unicast"
|
280
291
|
puts " * Websocket unicast testing: #{RESULTS[:waiting]}"
|
281
292
|
unicast_test ||= true
|
282
293
|
end
|
283
294
|
end
|
284
|
-
|
285
|
-
|
286
|
-
ws1 = GRHttp::WSClient.connect_to("ws://localhost:3000") do |ws|
|
295
|
+
puts " * Websocket client test: #{RESULTS[ws2 && true]}"
|
296
|
+
ws1 = Iodine::Http::WebsocketClient.connect("ws://localhost:3000") do |data|
|
287
297
|
unless @connected
|
288
|
-
puts " * Websocket connection message test: #{RESULTS[connection_test = (
|
298
|
+
puts " * Websocket connection message test: #{RESULTS[connection_test = (data == 'connected')]}"
|
289
299
|
@connected = true
|
290
|
-
|
300
|
+
write "echo test"
|
291
301
|
next
|
292
302
|
end
|
293
|
-
if
|
303
|
+
if data == "unicast"
|
294
304
|
puts " * Websocket unicast testing: #{RESULTS[false]}"
|
295
305
|
unicast_test = :failed
|
296
306
|
next
|
297
307
|
end
|
298
|
-
puts " * Websocket echo message test: #{RESULTS[echo_test = (
|
308
|
+
puts " * Websocket echo message test: #{RESULTS[echo_test = (data == 'echo test')]}"
|
299
309
|
end
|
300
310
|
|
301
311
|
rescue => e
|
302
312
|
puts " **** Websocket tests FAILED TO RUN!!!"
|
303
313
|
puts e.message
|
304
314
|
end
|
305
|
-
remote =
|
315
|
+
remote = Iodine::Http::WebsocketClient.connect("wss://echo.websocket.org/") {|data| puts " * Extra Websocket Remote test (SSL: echo.websocket.org): #{RESULTS[data == 'Hello websockets!']}"; close}
|
306
316
|
if remote.closed?
|
307
317
|
puts " * Extra Websocket Remote test (SSL: echo.websocket.org): #{RESULTS[false]}"
|
308
318
|
else
|
@@ -317,13 +327,12 @@ module PleziTestTasks
|
|
317
327
|
end
|
318
328
|
def test_websocket_sizes
|
319
329
|
should_disconnect = false
|
320
|
-
ws =
|
330
|
+
ws = Iodine::Http::WebsocketClient.connect("ws://localhost:3000/ws/size") do |data|
|
321
331
|
if should_disconnect
|
322
332
|
puts " * Websocket size disconnection test: #{RESULTS[false]}"
|
323
333
|
else
|
324
|
-
puts " * Websocket message size test: got #{
|
334
|
+
puts " * Websocket message size test: got #{data.bytesize} bytes"
|
325
335
|
end
|
326
|
-
|
327
336
|
end
|
328
337
|
ws.on_close do
|
329
338
|
puts " * Websocket size disconnection test: #{RESULTS[should_disconnect]}"
|
@@ -335,13 +344,16 @@ module PleziTestTasks
|
|
335
344
|
to_sleep = (Time.now - time_now)*2 + 1
|
336
345
|
puts "will now sleep for #{to_sleep} seconds, waiting allowing the server to respond"
|
337
346
|
sleep to_sleep rescue true
|
338
|
-
should_disconnect = true
|
339
347
|
Plezi::Settings.ws_message_size_limit = 1024
|
348
|
+
should_disconnect = true
|
340
349
|
ws << ('0123'*258)
|
350
|
+
sleep 0.3
|
351
|
+
should_disconnect = false
|
341
352
|
end
|
342
353
|
def test_broadcast_stress
|
343
354
|
PlaceboStressTestCtrl.create_listeners
|
344
355
|
PlaceboStressTestCtrl.run_test
|
356
|
+
PlaceboStressTestCtrl.unicast ($failed_uuid = Plezi::Settings.uuid + PlaceboStressTestCtrl.object_id.to_s(16) ), :review
|
345
357
|
end
|
346
358
|
def test_404
|
347
359
|
puts " * 404 not found and router continuity tests: #{RESULTS[ Net::HTTP.get_response(URI.parse "http://localhost:3000/get404" ).code == '404' ]}"
|
@@ -351,14 +363,7 @@ module PleziTestTasks
|
|
351
363
|
puts e
|
352
364
|
end
|
353
365
|
def test_500
|
354
|
-
|
355
|
-
print " * 500 internal error test: #{RESULTS[ Net::HTTP.get_response(URI.parse "http://localhost:3000/fail" ).code == '500' ]}"
|
356
|
-
# cause 10 more exceptions to be raised... testing thread survival.
|
357
|
-
10.times { putc "."; Net::HTTP.get_response(URI.parse "http://localhost:3000/fail" ).code }
|
358
|
-
putc "\n"
|
359
|
-
workers_after_test = GReactor.instance_exec {@threads.select {|t| t.alive?} .count}
|
360
|
-
puts " * Worker survival test: #{RESULTS[workers_after_test == workers]} (#{workers_after_test} out of #{workers})"
|
361
|
-
|
366
|
+
puts " * 500 internal error test: #{RESULTS[ Net::HTTP.get_response(URI.parse "http://localhost:3000/fail" ).code == '500' ]}"
|
362
367
|
rescue => e
|
363
368
|
puts " **** 500 internal error test FAILED TO RUN!!!"
|
364
369
|
puts e
|
@@ -408,6 +413,9 @@ class PlaceboStressTestCtrl
|
|
408
413
|
PlaceboStressTestCtrl.run_unicast_test unless uni
|
409
414
|
end
|
410
415
|
end
|
416
|
+
def self.failed_unicast target, method, data
|
417
|
+
puts " * Unicasting failure callback testing: #{PleziTestTasks::RESULTS[$failed_uuid == target]}"
|
418
|
+
end
|
411
419
|
def self.run_test
|
412
420
|
puts "\n * Placebo Broadcast stress test starting - (#{LISTENERS} listening objects with #{REPEATS} messages."
|
413
421
|
start_time = Time.now
|
@@ -424,28 +432,19 @@ class PlaceboStressTestCtrl
|
|
424
432
|
end
|
425
433
|
def self.create_listeners
|
426
434
|
@uuid = nil
|
427
|
-
LISTENERS.times {@uuid = Plezi::Placebo.new(PlaceboStressTestCtrl).uuid}
|
435
|
+
LISTENERS.times { @uuid = Plezi::Placebo.new(PlaceboStressTestCtrl).uuid }
|
436
|
+
sleep 0.5
|
437
|
+
puts " * Placebo creation test: #{PleziTestTasks::RESULTS[ Iodine.to_a.length >= LISTENERS ] }"
|
428
438
|
end
|
429
439
|
REPEATS = 1000
|
430
|
-
LISTENERS =
|
440
|
+
LISTENERS = 100
|
431
441
|
end
|
432
442
|
|
433
|
-
|
434
|
-
# PL::Settings.max_threads = 4
|
435
|
-
|
436
|
-
listen port: 3000
|
437
|
-
|
438
|
-
route("/ssl") {|req, res| res << "false" }
|
439
|
-
listen port: 3030, ssl: true
|
440
|
-
route("/ssl") {|req, res| res << "true" }
|
443
|
+
host
|
441
444
|
|
442
445
|
shared_route 'ws/no', Nothing
|
443
446
|
shared_route 'ws/placebo', PlaceboTestCtrl
|
444
447
|
shared_route 'ws/size', WSsizeTestCtrl
|
445
|
-
|
446
|
-
|
447
|
-
# puts Nothing.ancestors.join "\n"
|
448
|
-
|
449
448
|
shared_route '/some/:multi{path|another_path}/(:option){route|test}/(:id)/(:optional)', TestCtrl
|
450
449
|
shared_route '/', TestCtrl
|
451
450
|
|
@@ -459,40 +458,30 @@ mem_print_proc = Proc.new do
|
|
459
458
|
end
|
460
459
|
# puts ("\n\n*** GC.stat:\n" + ((GC.stat.merge ObjectSpace.count_objects_size).to_a.map {|i| i.join ': '} .join "\n"))
|
461
460
|
# mem_print_proc.call
|
462
|
-
#
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
puts " --- Plezi will ran async, performing some tests that than hang"
|
468
|
-
|
469
|
-
puts " --- Starting tests"
|
470
|
-
puts " --- Failed tests should read: #{PleziTestTasks::RESULTS[false]}"
|
471
|
-
|
472
|
-
r = Plezi::Placebo.new PlaceboCtrl
|
473
|
-
puts " * Create Placebo test: #{PleziTestTasks::RESULTS[r && true]}"
|
474
|
-
puts " * Placebo admists to being placebo: #{PleziTestTasks::RESULTS[PlaceboCtrl.placebo?]}"
|
475
|
-
puts " * Regular controller answers placebo: #{PleziTestTasks::RESULTS[!PlaceboTestCtrl.placebo?]}"
|
476
|
-
|
477
|
-
|
478
|
-
Plezi.start_async
|
479
|
-
PleziTestTasks.run_tests
|
461
|
+
# Plezi.run_every 30, &mem_print_proc
|
480
462
|
|
463
|
+
# require 'redis'
|
481
464
|
# ENV['PL_REDIS_URL'] ||= ENV['REDIS_URL'] || ENV['REDISCLOUD_URL'] || ENV['REDISTOGO_URL'] || "redis://test:1234@pub-redis-11008.us-east-1-4.5.ec2.garantiadata.com:11008"
|
482
|
-
#
|
483
|
-
# GR.run_async { PleziTestTasks.run_tests }
|
484
|
-
# start_services
|
485
|
-
|
486
|
-
shoutdown_test = false
|
487
|
-
Plezi.on_shutdown { shoutdown_test = true }
|
465
|
+
# Plezi.processes = 3
|
488
466
|
|
489
|
-
|
490
|
-
|
491
|
-
# Plezi::EventMachine.clear_timers
|
467
|
+
Plezi.threads = 9
|
468
|
+
PL.logger = nil
|
492
469
|
|
493
|
-
|
470
|
+
Plezi.run do
|
494
471
|
|
472
|
+
puts " --- Plezi #{Plezi::VERSION} will start a server, performing some tests."
|
473
|
+
puts " --- Starting tests"
|
474
|
+
puts " --- Failed tests should read: #{PleziTestTasks::RESULTS[false]}"
|
495
475
|
|
496
|
-
|
476
|
+
r = Plezi::Placebo.new PlaceboCtrl
|
477
|
+
puts " * Create Placebo test: #{PleziTestTasks::RESULTS[r && true]}"
|
478
|
+
puts " * Placebo admists to being placebo: #{PleziTestTasks::RESULTS[PlaceboCtrl.placebo?]}"
|
479
|
+
puts " * Regular controller answers placebo: #{PleziTestTasks::RESULTS[!PlaceboTestCtrl.placebo?]}"
|
497
480
|
|
481
|
+
PleziTestTasks.run_tests
|
498
482
|
|
483
|
+
shoutdown_test = false
|
484
|
+
Plezi.on_shutdown { puts " * Shutdown test: #{ PleziTestTasks::RESULTS[shoutdown_test] }" }
|
485
|
+
Plezi.on_shutdown { shoutdown_test = true }
|
486
|
+
|
487
|
+
end
|