sbsm 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/COPYING +515 -0
  2. data/History.txt +5 -0
  3. data/Manifest.txt +49 -0
  4. data/README.txt +41 -0
  5. data/Rakefile +28 -0
  6. data/data/_flavored_uri.grammar +24 -0
  7. data/data/_uri.grammar +22 -0
  8. data/data/_zone_uri.grammar +24 -0
  9. data/data/flavored_uri.grammar +24 -0
  10. data/data/uri.grammar +22 -0
  11. data/data/zone_uri.grammar +24 -0
  12. data/install.rb +1098 -0
  13. data/lib/cgi/drbsession.rb +37 -0
  14. data/lib/sbsm/cgi.rb +79 -0
  15. data/lib/sbsm/drb.rb +19 -0
  16. data/lib/sbsm/drbserver.rb +162 -0
  17. data/lib/sbsm/exception.rb +28 -0
  18. data/lib/sbsm/flavored_uri_parser.rb +47 -0
  19. data/lib/sbsm/index.rb +66 -0
  20. data/lib/sbsm/lookandfeel.rb +176 -0
  21. data/lib/sbsm/lookandfeelfactory.rb +50 -0
  22. data/lib/sbsm/lookandfeelwrapper.rb +109 -0
  23. data/lib/sbsm/redefine_19_cookie.rb +4 -0
  24. data/lib/sbsm/redirector.rb +37 -0
  25. data/lib/sbsm/request.rb +162 -0
  26. data/lib/sbsm/session.rb +542 -0
  27. data/lib/sbsm/state.rb +301 -0
  28. data/lib/sbsm/time.rb +29 -0
  29. data/lib/sbsm/trans_handler.rb +119 -0
  30. data/lib/sbsm/turing.rb +25 -0
  31. data/lib/sbsm/uri_parser.rb +45 -0
  32. data/lib/sbsm/user.rb +47 -0
  33. data/lib/sbsm/validator.rb +256 -0
  34. data/lib/sbsm/viralstate.rb +47 -0
  35. data/lib/sbsm/zone_uri_parser.rb +48 -0
  36. data/test/data/dos_file.txt +2 -0
  37. data/test/data/lnf_file.txt +2 -0
  38. data/test/data/mac_file.txt +1 -0
  39. data/test/stub/cgi.rb +35 -0
  40. data/test/suite.rb +29 -0
  41. data/test/test_drbserver.rb +83 -0
  42. data/test/test_index.rb +90 -0
  43. data/test/test_lookandfeel.rb +230 -0
  44. data/test/test_session.rb +372 -0
  45. data/test/test_state.rb +176 -0
  46. data/test/test_trans_handler.rb +447 -0
  47. data/test/test_user.rb +44 -0
  48. data/test/test_validator.rb +126 -0
  49. data/usage-en.txt +112 -0
  50. metadata +142 -0
@@ -0,0 +1,372 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # State Based Session Management
4
+ # Copyright (C) 2004 Hannes Wyss
5
+ #
6
+ # This library is free software; you can redistribute it and/or
7
+ # modify it under the terms of the GNU Lesser General Public
8
+ # License as published by the Free Software Foundation; either
9
+ # version 2.1 of the License, or (at your option) any later version.
10
+ #
11
+ # This library is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ # Lesser General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public
17
+ # License along with this library; if not, write to the Free Software
18
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ #
20
+ # ywesee - intellectual capital connected, Winterthurerstrasse 52, CH-8006 Z�rich, Switzerland
21
+ # hwyss@ywesee.com
22
+ #
23
+ # TestSession -- sbsm -- 22.10.2002 -- hwyss@ywesee.com
24
+
25
+ require 'test/unit'
26
+ require 'sbsm/session'
27
+ #require 'htmlgrid/component'
28
+
29
+ class StubSessionUnknownUser
30
+ end
31
+ class StubSessionApp
32
+ def unknown_user
33
+ StubSessionUnknownUser.new
34
+ end
35
+ def login(session)
36
+ false
37
+ end
38
+ def async(&block)
39
+ block.call
40
+ end
41
+ end
42
+ class StubSessionValidator
43
+ def reset_errors; end
44
+ def validate(key, value, mandatory=false)
45
+ value
46
+ end
47
+ def valid_values(key)
48
+ if(key=='foo')
49
+ ['foo', 'bar']
50
+ end
51
+ end
52
+ def error?
53
+ false
54
+ end
55
+ end
56
+ class StubSessionRequest < Hash
57
+ attr_accessor :unparsed_uri
58
+ def params
59
+ self
60
+ end
61
+ def cookies
62
+ {}
63
+ end
64
+ def request_method
65
+ 'GET'
66
+ end
67
+ end
68
+ class StubSessionView
69
+ def http_headers
70
+ {
71
+ "foo" => "bar"
72
+ }
73
+ end
74
+ def initialize(foo, bar)
75
+ end
76
+ def to_html(context)
77
+ '0123456789' * 3
78
+ end
79
+ end
80
+ class StubSessionBarState < SBSM::State
81
+ EVENT_MAP = {
82
+ :foobar => StubSessionBarState,
83
+ }
84
+ end
85
+ class StubSessionBarfoosState < SBSM::State
86
+ DIRECT_EVENT = :barfoos
87
+ end
88
+ class StubSessionFooState < SBSM::State
89
+ EVENT_MAP = {
90
+ :bar => StubSessionBarState
91
+ }
92
+ end
93
+ class StubSessionState < SBSM::State
94
+ VIEW = StubSessionView
95
+ attr_accessor :volatile
96
+ def foo
97
+ @foo ||= StubSessionFooState.new(@session,@model)
98
+ end
99
+ end
100
+ class StubVolatileState < SBSM::State
101
+ VOLATILE = true
102
+ end
103
+ class Session < SBSM::Session
104
+ DEFAULT_STATE = StubSessionState
105
+ DRB_LOAD_LIMIT = 10
106
+ CAP_MAX_THRESHOLD = 3
107
+ MAX_STATES = 3
108
+ DEFAULT_FLAVOR = 'gcc'
109
+ attr_accessor :user, :state
110
+ attr_accessor :attended_states, :cached_states
111
+ attr_writer :lookandfeel, :persistent_user_input
112
+ attr_writer :active_state
113
+ public :active_state
114
+ end
115
+ class StubSessionSession < SBSM::Session
116
+ attr_accessor :lookandfeel
117
+ attr_accessor :persistent_user_input
118
+ DEFAULT_FLAVOR = 'gcc'
119
+ LF_FACTORY = {
120
+ 'gcc' => 'ccg',
121
+ 'sbb' => 'bbs',
122
+ }
123
+ def initialize(*args)
124
+ super
125
+ persistent_user_input = {}
126
+ end
127
+ def persistent_user_input(key)
128
+ super
129
+ end
130
+ end
131
+
132
+ class TestSession < Test::Unit::TestCase
133
+ def setup
134
+ @session = Session.new("test", StubSessionApp.new, StubSessionValidator.new)
135
+ @request = StubSessionRequest.new
136
+ @state = StubSessionState.new(@session, nil)
137
+ end
138
+ def test_attended_states_store
139
+ @session.process(@request)
140
+ state = @session.state
141
+ expected = {
142
+ state.object_id => state
143
+ }
144
+ #puts 'test'
145
+ #puts @state
146
+ assert_equal(expected, @session.attended_states)
147
+ end
148
+ def test_attended_states_cap_max
149
+ req1 = StubSessionRequest.new
150
+ @session.process(req1)
151
+ state1 = @session.state
152
+ req2 = StubSessionRequest.new
153
+ req2["event"] = "foo"
154
+ @session.process(req2)
155
+ state2 = @session.state
156
+ assert_not_equal(state1, state2)
157
+ req3 = StubSessionRequest.new
158
+ req3["event"] = :bar
159
+ @session.process(req3)
160
+ state3 = @session.state
161
+ assert_not_equal(state1, state3)
162
+ assert_not_equal(state2, state3)
163
+ attended = {
164
+ state1.object_id => state1,
165
+ state2.object_id => state2,
166
+ state3.object_id => state3,
167
+ }
168
+ assert_equal(attended, @session.attended_states)
169
+ req4 = StubSessionRequest.new
170
+ req4["event"] = :foobar
171
+ @session.process(req4)
172
+ @session.cap_max_states
173
+ state4 = @session.state
174
+ assert_not_equal(state1, state4)
175
+ assert_not_equal(state2, state4)
176
+ assert_not_equal(state3, state4)
177
+ attended = {
178
+ state2.object_id => state2,
179
+ state3.object_id => state3,
180
+ state4.object_id => state4,
181
+ }
182
+ assert_equal(attended, @session.attended_states)
183
+ end
184
+ def test_active_state1
185
+ # Szenarien
186
+ # - Keine State-Information in User-Input
187
+ # - Unbekannter State in User-Input
188
+ # - Bekannter State in User-Input
189
+
190
+ state = StubSessionState.new(@session, nil)
191
+ @session.attended_states = {
192
+ state.object_id => state,
193
+ }
194
+ @session.active_state = @state
195
+ assert_equal(@state, @session.active_state)
196
+ end
197
+ def test_active_state2
198
+ # Szenarien
199
+ # - Keine State-Information in User-Input
200
+ # - Unbekannter State in User-Input
201
+ # - Bekannter State in User-Input
202
+
203
+ state = StubSessionState.new(@session, nil)
204
+ @session.attended_states = {
205
+ state.object_id => state,
206
+ }
207
+ @session.active_state = @state
208
+ @request.store('state_id', state.object_id.next)
209
+ @session.process(@request)
210
+ assert_equal(@state, @session.active_state)
211
+ end
212
+ def test_active_state3
213
+ # Szenarien
214
+ # - Keine State-Information in User-Input
215
+ # - Unbekannter State in User-Input
216
+ # - Bekannter State in User-Input
217
+
218
+ state = StubSessionState.new(@session, nil)
219
+ @session.attended_states = {
220
+ state.object_id => state,
221
+ }
222
+ @session.state = @state
223
+ @request.store('state_id', state.object_id)
224
+ @session.process(@request)
225
+ assert_equal(state, @session.active_state)
226
+ end
227
+ def test_volatile_state
228
+ state = StubSessionState.new(@session, nil)
229
+ volatile = StubVolatileState.new(@session, nil)
230
+ state.volatile = volatile
231
+ @session.active_state = state
232
+ @session.state = state
233
+ @request.store('event', :volatile)
234
+ newstate = @session.process(@request)
235
+ assert_equal(:volatile, @session.event)
236
+ assert_equal(volatile, @session.state)
237
+ assert_equal(state, @session.active_state)
238
+ @request.store('event', :foo)
239
+ newstate = @session.process(@request)
240
+ assert_equal(state.foo, @session.state)
241
+ assert_equal(state.foo, @session.active_state)
242
+ end
243
+ def test_cgi_compatible
244
+ assert_respond_to(@session, :restore)
245
+ assert_respond_to(@session, :update)
246
+ assert_respond_to(@session, :close)
247
+ assert_respond_to(@session, :delete)
248
+ end
249
+ def test_restore
250
+ assert_instance_of(Session, @session.restore[:proxy])
251
+ end
252
+ def test_user_input_no_request
253
+ assert_nil(@session.user_input(:no_input))
254
+ end
255
+ def test_user_input_nil
256
+ @session.process(@request)
257
+ assert_nil(@session.user_input(:no_input))
258
+ end
259
+ def test_user_input
260
+ @request["foo"] = "bar"
261
+ @request["baz"] = "zuv"
262
+ @session.process(@request)
263
+ assert_equal("bar", @session.user_input(:foo))
264
+ assert_equal("zuv", @session.user_input(:baz))
265
+ assert_equal("zuv", @session.user_input(:baz))
266
+ result = @session.user_input(:foo, :baz)
267
+ expected = {
268
+ :foo => 'bar',
269
+ :baz => 'zuv',
270
+ }
271
+ assert_equal(expected, result)
272
+ end
273
+ def test_user_input_hash
274
+ @request["hash[1]"] = "4"
275
+ @request["hash[2]"] = "5"
276
+ @request["hash[3]"] = "6"
277
+ @session.process(@request)
278
+ hash = @session.user_input(:hash)
279
+ assert_equal(Hash, hash.class)
280
+ assert_equal(3, hash.size)
281
+ assert_equal("4", hash["1"])
282
+ assert_equal("5", hash["2"])
283
+ assert_equal("6", hash["3"])
284
+ end
285
+ def test_http_headers
286
+ expected = {
287
+ "foo" => "bar"
288
+ }
289
+ assert_equal(expected, @session.http_headers)
290
+ end
291
+ def test_http_protocol
292
+ assert_equal("http", @session.http_protocol)
293
+ end
294
+ def test_login_fail_keep_user
295
+ @session.login
296
+ assert_equal(StubSessionUnknownUser, @session.user.class)
297
+ end
298
+ def test_logged_in
299
+ assert_equal(StubSessionUnknownUser, @session.user.class)
300
+ assert_equal(false, @session.logged_in?)
301
+ end
302
+ def test_valid_values
303
+ assert_equal(['foo', 'bar'], @session.valid_values('foo'))
304
+ assert_equal([], @session.valid_values('oof'))
305
+ end
306
+ def test_persistent_user_input
307
+ @request["baz"] = "zuv"
308
+ @session.process(@request)
309
+ assert_equal("zuv", @session.persistent_user_input(:baz))
310
+ @session.process(StubSessionRequest.new)
311
+ assert_equal("zuv", @session.persistent_user_input(:baz))
312
+ @request["baz"] = "bla"
313
+ @session.process(@request)
314
+ assert_equal("bla", @session.persistent_user_input(:baz))
315
+ end
316
+ def test_process
317
+ state = StubSessionState.new(@session, nil)
318
+ @session.attended_states = {
319
+ state.object_id => state,
320
+ }
321
+ @session.state = @state
322
+ expected = state.foo
323
+ @request.store('state_id', state.object_id)
324
+ @request.store('event', :foo)
325
+ @session.process(@request)
326
+ assert_equal(expected, @session.state)
327
+ assert_equal(expected, @session.attended_states[expected.object_id])
328
+ end
329
+ def test_logout
330
+ state = StubSessionBarState.new(@session, nil)
331
+ @session.attended_states.store(state.object_id, state)
332
+ assert_equal(state, @session.attended_states[state.object_id])
333
+ @session.logout
334
+ assert_equal(1, @session.attended_states.size)
335
+ end
336
+ def test_lookandfeel
337
+ @session.lookandfeel=nil
338
+ @session.persistent_user_input = {
339
+ :flavor => 'some',
340
+ }
341
+ lnf = @session.lookandfeel
342
+ assert_equal('gcc', @session.flavor)
343
+ assert_equal('gcc', lnf.flavor)
344
+ assert_instance_of(SBSM::Lookandfeel, lnf)
345
+ lnf2 = @session.lookandfeel
346
+ assert_equal(lnf, lnf2)
347
+ @session.persistent_user_input = {
348
+ :flavor => 'other',
349
+ }
350
+ lnf3 = @session.lookandfeel
351
+ assert_instance_of(SBSM::Lookandfeel, lnf)
352
+ assert_equal(lnf, lnf3) ## flavor does not change!
353
+ end
354
+ def test_lookandfeel2
355
+ session = StubSessionSession.new("test", StubSessionApp.new, StubSessionValidator.new)
356
+ session.lookandfeel=nil
357
+ session.persistent_user_input = {
358
+ :flavor => 'gcc',
359
+ }
360
+ lnf = session.lookandfeel
361
+ assert_equal('gcc', session.flavor)
362
+ end
363
+ def test_lookandfeel3
364
+ session = StubSessionSession.new("test", StubSessionApp.new, StubSessionValidator.new)
365
+ session.lookandfeel=nil
366
+ lnf2 = session.lookandfeel
367
+ session.persistent_user_input = {
368
+ :flavor => 'other',
369
+ }
370
+ assert_equal('gcc', session.flavor)
371
+ end
372
+ end
@@ -0,0 +1,176 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # State Based Session Management
4
+ # Copyright (C) 2004 Hannes Wyss
5
+ #
6
+ # This library is free software; you can redistribute it and/or
7
+ # modify it under the terms of the GNU Lesser General Public
8
+ # License as published by the Free Software Foundation; either
9
+ # version 2.1 of the License, or (at your option) any later version.
10
+ #
11
+ # This library is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ # Lesser General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public
17
+ # License along with this library; if not, write to the Free Software
18
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ #
20
+ # ywesee - intellectual capital connected, Winterthurerstrasse 52, CH-8006 Z�rich, Switzerland
21
+ # hwyss@ywesee.com
22
+ #
23
+ # TestState -- oddb -- 20.11.2002 -- hwyss@ywesee.com
24
+
25
+ $: << File.dirname(__FILE__)
26
+ $: << File.expand_path("../lib", File.dirname(__FILE__))
27
+
28
+ require 'test/unit'
29
+ require 'sbsm/state'
30
+
31
+ class StubStateState1
32
+ attr_accessor :previous
33
+ def initialize(*args)
34
+ end
35
+ def reset_view
36
+ end
37
+ end
38
+ class StubStateState2
39
+ attr_accessor :previous
40
+ def initialize(*args)
41
+ end
42
+ def reset_view
43
+ end
44
+ end
45
+ class StubStateState3
46
+ attr_accessor :previous
47
+ def initialize(*args)
48
+ end
49
+ def reset_view
50
+ end
51
+ end
52
+ class StubStateView
53
+ attr_reader :model, :session
54
+ def initialize(model, session)
55
+ @model, @session = model, session
56
+ end
57
+ end
58
+ class StubStateUserView < StubStateView
59
+ end
60
+ class StubStateUser
61
+ end
62
+ class StubStateSession
63
+ def user
64
+ :test_default
65
+ end
66
+ end
67
+ class StubStateUserSession
68
+ def user
69
+ StubStateUser.new
70
+ end
71
+ end
72
+ class State < SBSM::State
73
+ attr_reader :init_called
74
+ attr_writer :errors, :session, :filter, :warnings
75
+ DIRECT_EVENT = :foo
76
+ EVENT_MAP = {
77
+ :bar => StubStateState1
78
+ }
79
+ GLOBAL_MAP = {
80
+ :baz => StubStateState2
81
+ }
82
+ VIEW = StubStateView
83
+ def himself
84
+ self
85
+ end
86
+ def buc
87
+ StubStateState3.new
88
+ end
89
+ def init
90
+ @init_called = true
91
+ end
92
+ end
93
+ class UserState < State
94
+ VIEW = {
95
+ :default => StubStateView,
96
+ StubStateUser => StubStateUserView,
97
+ }
98
+ end
99
+
100
+ class TestState < Test::Unit::TestCase
101
+ def setup
102
+ @state = State.new(nil, nil)
103
+ end
104
+ def test_direct_event
105
+ assert_equal(:foo, State.direct_event)
106
+ end
107
+ def test_trigger_default
108
+ assert_equal(@state, @state.trigger(:foo))
109
+ end
110
+ def test_trigger_event
111
+ assert_equal(StubStateState1, @state.trigger(:bar).class)
112
+ end
113
+ def test_trigger_global
114
+ assert_equal(StubStateState2, @state.trigger(:baz).class)
115
+ end
116
+ def test_trigger_method
117
+ assert_equal(StubStateState3, @state.trigger(:buc).class)
118
+ end
119
+ def test_errors
120
+ assert_equal(false, @state.error?)
121
+ @state.errors = {:de => 'ein Error'}
122
+ assert_equal(true, @state.error?)
123
+ assert_equal('ein Error', @state.error(:de))
124
+ new_state = @state.trigger(:himself)
125
+ assert_equal(@state, new_state)
126
+ assert_equal(false, @state.error?)
127
+
128
+ end
129
+ def test_default
130
+ assert_respond_to(@state, :default)
131
+ end
132
+ def test_warnings
133
+ assert_equal(false, @state.warning?)
134
+ warning = SBSM::Warning.new('eine Warnung', :foo, '')
135
+ @state.warnings = [warning]
136
+ assert_equal(true, @state.warning?)
137
+ assert_equal(warning, @state.warning(:foo))
138
+ new_state = @state.trigger(:himself)
139
+ assert_equal(@state, new_state)
140
+ assert_equal(false, @state.warning?)
141
+ @state.add_warning('A Message', 'key', 'A Value')
142
+ assert_equal(true, @state.warning?)
143
+ assert_equal(1, @state.warnings.size)
144
+ warning = @state.warnings.first
145
+ assert_equal(warning, @state.warning(:key))
146
+ assert_instance_of(SBSM::Warning, warning)
147
+ assert_equal('A Message', warning.message)
148
+ assert_equal(:key, warning.key)
149
+ assert_equal('A Value', warning.value)
150
+ @state.add_warning('Another Message', :key2, 'Another Value')
151
+ assert_equal(2, @state.warnings.size)
152
+ end
153
+ end
154
+ class TestUserState < Test::Unit::TestCase
155
+ def test_no_user_view_defined
156
+ state = State.new(StubStateSession.new, nil)
157
+ assert_equal(StubStateView, state.view.class)
158
+ end
159
+ def test_default_user_view
160
+ state = UserState.new(StubStateSession.new, nil)
161
+ assert_equal(StubStateView, state.view.class)
162
+ end
163
+ def test_user_view
164
+ state = UserState.new(StubStateUserSession.new, nil)
165
+ assert_equal(StubStateUserView, state.view.class)
166
+ end
167
+ def test_filtered_view
168
+ model = [1,2,3,4,5]
169
+ state = UserState.new(StubStateSession.new, model)
170
+ state.filter = Proc.new { |model|
171
+ model.select { |entry| entry > 2 }
172
+ }
173
+ view = state.view
174
+ assert_equal(3, view.model.size)
175
+ end
176
+ end