julien51-babylon 0.1.0 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -9,7 +9,7 @@ begin
9
9
  gem.email = "julien.genestoux@gmail.com"
10
10
  gem.homepage = "http://github.com/julien51/babylon"
11
11
  gem.authors = ["julien Genestoux"]
12
- gem.requirements = ["eventmachine", "yaml", "fileutils", "log4r", "nokogiri", "sax-machine", "templater", "daemons"]
12
+ gem.requirements = ["eventmachine", "yaml", "fileutils", "log4r", "nokogiri", "sax-machine", "templater", "daemons", "optparse", "digest/sha1", "base64", "resolv"]
13
13
  gem.executables = "babylon"
14
14
  gem.files = [ "bin/babylon",
15
15
  "lib/babylon.rb",
data/lib/babylon.rb CHANGED
@@ -7,6 +7,11 @@ require 'nokogiri'
7
7
  require 'yaml'
8
8
  require 'fileutils'
9
9
  require 'sax-machine'
10
+ require 'digest/sha1'
11
+ require 'base64'
12
+ require 'resolv'
13
+ require "templater"
14
+
10
15
 
11
16
  require 'babylon/xmpp_connection'
12
17
  require 'babylon/xmpp_parser'
@@ -1,5 +1,3 @@
1
- require "sax-machine"
2
-
3
1
  module Babylon
4
2
  module Base
5
3
  ##
@@ -5,9 +5,6 @@ module Babylon
5
5
  # So far, SASL Plain authenticationonly is supported
6
6
  # Upon stanza reception, and depending on the status (connected... etc), this component will handle or forward the stanzas.
7
7
  class ClientConnection < XmppConnection
8
- require 'digest/sha1'
9
- require 'base64'
10
- require 'resolv'
11
8
 
12
9
  attr_reader :binding_iq_id, :session_iq_id
13
10
 
@@ -56,15 +53,15 @@ module Babylon
56
53
  # Builds the stream stanza for this client
57
54
  def stream_stanza
58
55
  doc = Nokogiri::XML::Document.new
59
- stream = Nokogiri::XML::Node.new("stream", doc)
56
+ stream = Nokogiri::XML::Node.new("stream:stream", doc)
60
57
  doc.add_child(stream)
61
- stream.add_namespace(nil, stream_namespace())
62
- stream.add_namespace("stream", "http://etherx.jabber.org/streams")
58
+ stream["xmlns"] = stream_namespace
59
+ stream["xmlns:stream"] = "http://etherx.jabber.org/streams"
63
60
  stream["to"] = jid.split("/").first.split("@").last
64
61
  stream["version"] = "1.0"
65
62
  paste_content_here = Nokogiri::XML::Node.new("paste_content_here", doc)
66
63
  stream.add_child(paste_content_here)
67
- doc.to_xml.split('<stream:paste_content_here/>').first
64
+ doc.to_xml.split('<paste_content_here/>').first
68
65
  end
69
66
 
70
67
  ##
@@ -100,7 +97,7 @@ module Babylon
100
97
  doc = Nokogiri::XML::Document.new
101
98
  starttls = Nokogiri::XML::Node.new("starttls", doc)
102
99
  doc.add_child(starttls)
103
- starttls.add_namespace(nil, "urn:ietf:params:xml:ns:xmpp-tls")
100
+ starttls["xmlns"] = "urn:ietf:params:xml:ns:xmpp-tls"
104
101
  send_xml(starttls.to_s)
105
102
  @state = :wait_for_proceed
106
103
  elsif stanza.at("mechanisms") # tls is ok
@@ -109,7 +106,7 @@ module Babylon
109
106
  auth = Nokogiri::XML::Node.new("auth", doc)
110
107
  doc.add_child(auth)
111
108
  auth['mechanism'] = "PLAIN"
112
- auth.add_namespace(nil, "urn:ietf:params:xml:ns:xmpp-sasl")
109
+ auth["xmlns"] = "urn:ietf:params:xml:ns:xmpp-sasl"
113
110
  auth.content = Base64::encode64([jid, jid.split("@").first, @password].join("\000")).gsub(/\s/, '')
114
111
  send_xml(auth.to_s)
115
112
  @state = :wait_for_success
@@ -142,7 +139,7 @@ module Babylon
142
139
  iq["type"] = "set"
143
140
  iq["id"] = binding_iq_id.to_s
144
141
  bind = Nokogiri::XML::Node.new("bind", doc)
145
- bind.add_namespace(nil, "urn:ietf:params:xml:ns:xmpp-bind")
142
+ bind["xmlns"] = "urn:ietf:params:xml:ns:xmpp-bind"
146
143
  iq.add_child(bind)
147
144
  resource = Nokogiri::XML::Node.new("resource", doc)
148
145
  if jid.split("/").size == 2
@@ -169,7 +166,7 @@ module Babylon
169
166
  iq["type"] = "set"
170
167
  iq["id"] = session_iq_id.to_s
171
168
  session = Nokogiri::XML::Node.new("session", doc)
172
- session.add_namespace(nil, "urn:ietf:params:xml:ns:xmpp-session")
169
+ session["xmlns"] = "urn:ietf:params:xml:ns:xmpp-session"
173
170
  iq.add_child(session)
174
171
  send_xml(iq.to_s)
175
172
  @state = :wait_for_confirmed_session
@@ -3,7 +3,6 @@ module Babylon
3
3
  # ComponentConnection is in charge of the XMPP connection itself.
4
4
  # Upon stanza reception, and depending on the status (connected... etc), this component will handle or forward the stanzas.
5
5
  class ComponentConnection < XmppConnection
6
- require 'digest/sha1'
7
6
 
8
7
  ##
9
8
  # Creates a new ComponentConnection and waits for data in the stream
@@ -19,14 +18,14 @@ module Babylon
19
18
  def connection_completed
20
19
  super
21
20
  doc = Nokogiri::XML::Document.new
22
- stream = Nokogiri::XML::Node.new("stream", doc)
23
- stream.add_namespace(nil, stream_namespace)
24
- stream.add_namespace("stream", "http://etherx.jabber.org/streams")
21
+ stream = Nokogiri::XML::Node.new("stream:stream", doc)
22
+ stream["xmlns"] = stream_namespace
23
+ stream["xmlns:stream"] = "http://etherx.jabber.org/streams"
25
24
  stream["to"] = jid
26
25
  doc.add_child(stream)
27
26
  paste_content_here= Nokogiri::XML::Node.new("paste_content_here", doc)
28
27
  stream.add_child(paste_content_here)
29
- start, stop = doc.to_xml.split('<stream:paste_content_here/>')
28
+ start, stop = doc.to_xml.split('<paste_content_here/>')
30
29
  send_xml(start)
31
30
  end
32
31
 
@@ -1,5 +1,3 @@
1
- require "templater"
2
-
3
1
  module Babylon
4
2
  module Generator
5
3
  extend Templater::Manifold
@@ -12,7 +12,9 @@ module Babylon
12
12
  Babylon.config = YAML.load(config_file)[Babylon.environment]
13
13
 
14
14
  # Add an outputter to the logger
15
- Babylon.logger.add(Log4r::FileOutputter.new("#{Babylon.environment}", :filename => "log/#{Babylon.environment}.log", :trunc => false))
15
+ log_file = Log4r::RollingFileOutputter.new("#{Babylon.environment}", :filename => "log/#{Babylon.environment}.log", :trunc => false)
16
+ log_file.formatter = Log4r::PatternFormatter.new(:pattern => "%d (#{Process.pid}) [%l] :: %m", :date_pattern => "%d/%m %H:%M")
17
+ Babylon.logger.add(log_file)
16
18
 
17
19
  # Requiring all models, stanza, controllers
18
20
  ['app/models/*.rb', 'app/stanzas/*.rb', 'app/controllers/*_controller.rb'].each do |dir|
@@ -89,7 +89,7 @@ module Babylon
89
89
  def add_namespaces_and_attributes_to_current_node(attrs)
90
90
  (attrs.size / 2).times do |i|
91
91
  name, value = attrs[2 * i], attrs[2 * i + 1]
92
- # TODO : FIX namespaces :they give a lot of problems with XPath
92
+ # TODO : FIX namespaces :they give a lot of problems with Nokogiri
93
93
  # if name == "xmlns"
94
94
  # @elem.add_namespace(nil, value)
95
95
  # elsif name =~ /\Axmlns:/
File without changes
data/spec/em_mock.rb ADDED
@@ -0,0 +1,42 @@
1
+ ##
2
+ # Mock for EventMachine
3
+ module EventMachine
4
+
5
+ def self.mock?
6
+ true
7
+ end
8
+
9
+ ##
10
+ # Mock for the Connection Class
11
+ class Connection
12
+ def self.new(*args)
13
+ allocate.instance_eval do
14
+ # Call a superclass's #initialize if it has one
15
+ initialize(*args)
16
+ # Store signature and run #post_init
17
+ post_init
18
+ self
19
+ end
20
+ end
21
+ end
22
+
23
+ ##
24
+ # Stub for run
25
+ def self.run(proc)
26
+ proc.call
27
+ end
28
+
29
+ ##
30
+ # Stub for epoll
31
+ def self.epoll; end
32
+
33
+ ##
34
+ # Stub! to stop the event loop.
35
+ def self.stop_event_loop; end
36
+
37
+ ##
38
+ # Stub for connect (should return a connection object)
39
+ def self.connect(host, port, handler, params)
40
+ handler.new(params)
41
+ end
42
+ end
@@ -0,0 +1,205 @@
1
+ require File.dirname(__FILE__) + '/../../../spec_helper'
2
+
3
+ describe Babylon::Base::Controller do
4
+
5
+ before(:each) do
6
+ Babylon.views.stub!(:[]).and_return("") # Stubbing read for view
7
+ end
8
+
9
+ describe ".initialize" do
10
+ before(:each) do
11
+ @params = {:a => "a", :b => 1, :c => {:key => "value"}, :stanza => "<hello>world</hello>"}
12
+ end
13
+
14
+ it "should have a stanza instance" do
15
+ stanza = mock(Object)
16
+ c = Babylon::Base::Controller.new(stanza)
17
+
18
+ c.instance_variables.should be_include "@stanza"
19
+ c.instance_variable_get("@stanza").should == stanza
20
+ end
21
+
22
+ it "should not be rendered yet" do
23
+ c = Babylon::Base::Controller.new(@params)
24
+ c.rendered.should_not be_true
25
+ end
26
+ end
27
+
28
+ describe ".perform" do
29
+ before(:each) do
30
+ @action = :subscribe
31
+ params = {:stanza => "<hello>world</hello>"}
32
+ @controller = Babylon::Base::Controller.new(params)
33
+ @controller.class.send(:define_method, @action) do # Defining the action method
34
+ # Do something
35
+ end
36
+ end
37
+
38
+ it "should setup the action to the param" do
39
+ @controller.perform(@action) do
40
+ # Do something
41
+ end
42
+ @controller.instance_variable_get("@action_name").should == @action
43
+ end
44
+
45
+ it "should call the action" do
46
+ @controller.should_receive(:send).with(@action).and_return()
47
+ @controller.perform(@action) do
48
+ # Do something
49
+ end
50
+ end
51
+
52
+ it "should write an error to the log in case of failure of the action" do
53
+ @controller.stub!(:send).with(@action).and_raise(StandardError)
54
+ Babylon.logger.should_receive(:error)
55
+ @controller.perform(@action) do
56
+ # Do something
57
+ end
58
+ end
59
+
60
+ it "should call render" do
61
+ @controller.should_receive(:render)
62
+ @controller.perform(@action) do
63
+ # Do something
64
+ end
65
+ end
66
+ end
67
+
68
+ describe ".render" do
69
+ before(:each) do
70
+ @controller = Babylon::Base::Controller.new({})
71
+ @controller.action_name = :subscribe
72
+ end
73
+
74
+ it "should assign a value to view" do
75
+ @controller.render
76
+ @controller.instance_variable_get("@view").should_not be_nil
77
+ end
78
+
79
+ describe "with :nothing option" do
80
+ it "should not render any file" do
81
+ @controller.should_not_receive(:render_for_file)
82
+ @controller.render :nothing => true
83
+ end
84
+ end
85
+
86
+ describe "with no option" do
87
+ it "should call render with default_file_name if no option is provided" do
88
+ @controller.should_receive(:default_template_name)
89
+ @controller.render
90
+ end
91
+ end
92
+
93
+ describe "with an :action option" do
94
+ it "should call render with the file name corresponding to the action given as option" do
95
+ action = :unsubscribe
96
+ @controller.should_receive(:default_template_name).with("#{action}")
97
+ @controller.render(:action => action)
98
+ end
99
+ end
100
+
101
+ describe "with a file option" do
102
+ it "should call render_for_file with the correct path if an option file is provided" do
103
+ file = "myfile"
104
+ @controller.should_receive(:render_for_file)
105
+ @controller.render(:file => file)
106
+ end
107
+ end
108
+
109
+ it "should not render twice when called twice" do
110
+ @controller.render
111
+ @controller.should_not_receive(:render_for_file)
112
+ @controller.render
113
+ end
114
+ end
115
+
116
+ describe ".assigns" do
117
+
118
+ before(:each) do
119
+ @stanza = mock(Babylon::Base::Stanza)
120
+ @controller = Babylon::Base::Controller.new(@stanza)
121
+ end
122
+
123
+ it "should be a hash" do
124
+ @controller.assigns.should be_an_instance_of(Hash)
125
+ end
126
+
127
+ it "should only contain the @stanza if the action hasn't been called yet" do
128
+ @controller.assigns.should_not be_empty
129
+ @controller.assigns["stanza"].should == @stanza
130
+ end
131
+
132
+ it "should return an hash containing all instance variables defined in the action" do
133
+ vars = {"a" => 1, "b" => "b", "c" => { "d" => 4}}
134
+ class MyController < Babylon::Base::Controller
135
+ def do_something
136
+ @a = 1
137
+ @b = "b"
138
+ @c = { "d" => 4 }
139
+ end
140
+ end
141
+ @controller = MyController.new(@stanza)
142
+ @controller.do_something
143
+ @controller.assigns.should == vars.merge("stanza" => @stanza)
144
+ end
145
+ end
146
+
147
+ describe ".evaluate" do
148
+ before(:each) do
149
+ @controller = Babylon::Base::Controller.new()
150
+ end
151
+
152
+ it "should evaluate the view" do
153
+ view = mock(Babylon::Base::View)
154
+ response = "hello"
155
+ @controller.instance_variable_set("@view", view)
156
+ view.should_receive(:evaluate).and_return(response)
157
+ @controller.evaluate.should == response
158
+ end
159
+ end
160
+
161
+ describe ".view_path" do
162
+ it "should return complete file path to the file given in param" do
163
+ @controller = Babylon::Base::Controller.new()
164
+ file_name = "myfile"
165
+ @controller.__send__(:view_path, file_name).should == File.join("app/views", "#{"Babylon::Base::Controller".gsub("Controller","").downcase}", file_name)
166
+ end
167
+ end
168
+
169
+ describe ".default_template_name" do
170
+ before(:each) do
171
+ @controller = Babylon::Base::Controller.new()
172
+ end
173
+
174
+ it "should return the view file name if a file is given in param" do
175
+ @controller.__send__(:default_template_name, "myaction").should == "myaction.xml.builder"
176
+ end
177
+
178
+ it "should return the view file name based on the action_name if no file has been given" do
179
+ @controller.action_name = "a_great_action"
180
+ @controller.__send__(:default_template_name).should == "a_great_action.xml.builder"
181
+ end
182
+ end
183
+
184
+ describe ".render_for_file" do
185
+
186
+ before(:each) do
187
+ @controller = Babylon::Base::Controller.new()
188
+ @block = Proc.new {
189
+ # Do something
190
+ }
191
+ @controller.class.send(:define_method, "action") do # Defining the action method
192
+ # Do something
193
+ end
194
+ @controller.perform(:action, &@block)
195
+ @view = Babylon::Base::View.new("path_to_a_file", {})
196
+ end
197
+
198
+ it "should instantiate a new view, with the file provided and the hashed_variables" do
199
+ Babylon::Base::View.should_receive(:new).with("path_to_a_file",an_instance_of(Hash)).and_return(@view)
200
+ @controller.__send__(:render_for_file, "path_to_a_file")
201
+ end
202
+
203
+ end
204
+
205
+ end
@@ -0,0 +1,15 @@
1
+ require File.dirname(__FILE__) + '/../../../spec_helper'
2
+
3
+ describe Babylon::Base::Stanza do
4
+
5
+ describe "initialize" do
6
+ before(:each) do
7
+ @stanza_string = "<presence />"
8
+ @stanza = Babylon::Base::Stanza.new(@stanza_string)
9
+ end
10
+
11
+ it "should call parse with the string passed to the builder"
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,64 @@
1
+ require File.dirname(__FILE__) + '/../../../spec_helper'
2
+
3
+ describe Babylon::Base::View do
4
+ describe ".initialize" do
5
+
6
+ before(:each) do
7
+ @view = Babylon::Base::View.new("/a/path/to/a/view/file", {:a => "a", :b => 123, :c => {:d => "d", :e => "123"}})
8
+ end
9
+
10
+ it "should assign @view_template to path" do
11
+ @view.view_template == "/a/path/to/a/view/file"
12
+ end
13
+
14
+ it "should assign any variable passed in hash" do
15
+ {:a => "a", :b => 123, :c => {:d => "d", :e => "123"}}.each do |key, value|
16
+ @view.instance_variable_get("@#{key}").should == value
17
+ end
18
+ end
19
+ end
20
+
21
+ describe ".evaluate" do
22
+ before(:each) do
23
+ @view_template = "/a/path/to/a/view/file"
24
+ @view = Babylon::Base::View.new(@view_template, {:a => "a", :b => 123, :c => {:d => "d", :e => "123"}})
25
+ @xml_string = <<-eoxml
26
+ xml.message(:to => "you", :from => "me", :type => :chat) do
27
+ xml.body("salut")
28
+ end
29
+ eoxml
30
+ Babylon.views.stub!(:[]).with(@view_template).and_return(@xml_string)
31
+ end
32
+
33
+ it "should read the template file" do
34
+ Babylon.views.should_receive(:[]).twice.with(@view_template).and_return(@xml_string)
35
+ @view.evaluate
36
+ end
37
+
38
+ it "should raise an error if the view file couldn't be found" do
39
+ Babylon.views.stub!(:[]).with(@view_template).and_raise(nil)
40
+ lambda {
41
+ @view.evaluate
42
+ }.should raise_error(Babylon::Base::ViewFileNotFound)
43
+ end
44
+
45
+ it "should return a Nokogiri NodeSet" do
46
+ Babylon.views.stub!(:[]).with(@view_template).and_return(@xml_string)
47
+ @view.evaluate.should be_an_instance_of(Nokogiri::XML::NodeSet)
48
+ end
49
+
50
+ it "should call eval on the view file" do
51
+ Babylon.views.stub!(:[]).with(@view_template).and_return(@xml_string)
52
+ @view.should_receive(:eval).with(@xml_string)
53
+ @view.evaluate
54
+ end
55
+
56
+ it "should be able to access context's variables" do
57
+ @view = Babylon::Base::View.new("/a/path/to/a/view/file", {:a => "a", :b => 123, :c => {:d => "d", :e => "123"}})
58
+ @view.instance_variable_get("@a").should == "a"
59
+ @view.instance_variable_get("@b").should == 123
60
+ @view.instance_variable_get("@c").should == {:e=>"123", :d=>"d"}
61
+ end
62
+ end
63
+
64
+ end