motel 0.2 → 0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +35 -0
- data/Rakefile +48 -0
- data/bin/clients/simple/main.rb +131 -0
- data/bin/server/main.rb +61 -0
- data/conf/motel-schema.xml +72 -0
- data/lib/motel/common.rb +35 -11
- data/lib/motel/dsl.rb +12 -0
- data/lib/motel/exceptions.rb +14 -0
- data/lib/motel/location.rb +100 -0
- data/lib/motel/{models → movement_strategies}/elliptical.rb +51 -89
- data/lib/motel/movement_strategies/linear.rb +54 -0
- data/lib/motel/movement_strategies/stopped.rb +18 -0
- data/lib/motel/movement_strategy.rb +29 -0
- data/lib/motel/runner.rb +94 -108
- data/lib/motel/simrpc.rb +131 -0
- data/lib/motel/thread_pool.rb +51 -0
- data/lib/motel.rb +9 -5
- data/spec/common_spec.rb +77 -0
- data/spec/dsl_spec.rb +27 -0
- data/spec/location_spec.rb +109 -0
- data/spec/movement_strategies/elliptical_spec.rb +90 -0
- data/spec/movement_strategies/linear_spec.rb +51 -0
- data/spec/movement_strategies/stopped_spec.rb +39 -0
- data/spec/movement_strategy_spec.rb +24 -0
- data/spec/runner_spec.rb +45 -0
- data/spec/simrpc_spec.rb +85 -0
- data/spec/spec_helper.rb +26 -0
- metadata +36 -34
- data/README +0 -0
- data/conf/amqp.yml +0 -13
- data/conf/database.yml +0 -41
- data/db/migrate/001_create_locations_and_movement_strategies.rb +0 -45
- data/db/migrate/002_create_linear_movement_strategy.rb +0 -23
- data/db/migrate/003_create_elliptical_movement_strategy.rb +0 -52
- data/lib/motel/loader.rb +0 -47
- data/lib/motel/models/linear.rb +0 -76
- data/lib/motel/models/location.rb +0 -109
- data/lib/motel/models/movement_strategy.rb +0 -82
- data/lib/motel/models/stopped.rb +0 -16
@@ -0,0 +1,51 @@
|
|
1
|
+
# copied unmodified from the ruby cookbook
|
2
|
+
# http://codeidol.com/other/rubyckbk/Multitasking-and-Multithreading/Limiting-Multithreading-with-a-Thread-Pool/
|
3
|
+
|
4
|
+
require 'thread'
|
5
|
+
|
6
|
+
class ThreadPool
|
7
|
+
attr_reader :max_size
|
8
|
+
|
9
|
+
def initialize(max_size)
|
10
|
+
@pool = []
|
11
|
+
@max_size = max_size
|
12
|
+
@pool_mutex = Mutex.new
|
13
|
+
@pool_cv = ConditionVariable.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def dispatch(*args)
|
17
|
+
Thread.new do
|
18
|
+
# Wait for space in the pool.
|
19
|
+
@pool_mutex.synchronize do
|
20
|
+
while @pool.size >= @max_size
|
21
|
+
print "Pool is full; waiting to run #{args.join(',')}…\n" if $DEBUG
|
22
|
+
# Sleep until some other thread calls @pool_cv.signal.
|
23
|
+
@pool_cv.wait(@pool_mutex)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
@pool << Thread.current
|
27
|
+
begin
|
28
|
+
yield(*args)
|
29
|
+
rescue => e
|
30
|
+
exception(self, e, *args)
|
31
|
+
ensure
|
32
|
+
@pool_mutex.synchronize do
|
33
|
+
# Remove the thread from the pool.
|
34
|
+
@pool.delete(Thread.current)
|
35
|
+
# Signal the next waiting thread that there's a space in the pool.
|
36
|
+
@pool_cv.signal
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def shutdown
|
43
|
+
@pool_mutex.synchronize { @pool_cv.wait(@pool_mutex) until @pool.empty? }
|
44
|
+
end
|
45
|
+
|
46
|
+
def exception(thread, exception, *original_args)
|
47
|
+
# Subclass this method to handle an exception within a thread.
|
48
|
+
puts "Exception in thread #{thread}: #{exception}"
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
data/lib/motel.rb
CHANGED
@@ -1,13 +1,17 @@
|
|
1
1
|
# include all motel modules
|
2
2
|
#
|
3
|
-
# Copyright (C)
|
4
|
-
#
|
3
|
+
# Copyright (C) 2010 Mohammed Morsi <movitto@yahoo.com>
|
4
|
+
# Licensed under the AGPLv3+ http://www.gnu.org/licenses/agpl.txt
|
5
5
|
|
6
6
|
lib = File.dirname(__FILE__)
|
7
7
|
|
8
|
-
require lib + '/motel/
|
8
|
+
require lib + '/motel/exceptions'
|
9
9
|
require lib + '/motel/runner'
|
10
|
-
require lib + '/motel/loader'
|
11
10
|
require lib + '/motel/simrpc'
|
12
11
|
|
13
|
-
|
12
|
+
require lib + '/motel/dsl'
|
13
|
+
|
14
|
+
require lib + '/motel/location'
|
15
|
+
require lib + '/motel/movement_strategy'
|
16
|
+
|
17
|
+
Dir[lib + '/motel/movement_strategies/*.rb'].each { |model| require model }
|
data/spec/common_spec.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# common module tests
|
2
|
+
#
|
3
|
+
# Copyright (C) 2010 Mohammed Morsi <movitto@yahoo.com>
|
4
|
+
# Licensed under the AGPLv3+ http://www.gnu.org/licenses/agpl.txt
|
5
|
+
|
6
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
7
|
+
|
8
|
+
describe "gen_uuid" do
|
9
|
+
|
10
|
+
it "should generate valid uuid" do
|
11
|
+
uuid = gen_uuid
|
12
|
+
uuid.size.should == 36
|
13
|
+
uuid.should =~ /[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "normalize" do
|
19
|
+
|
20
|
+
it "shoud not affect a normalized vector" do
|
21
|
+
x,y,z = normalize 1,0,0
|
22
|
+
x.should be(1)
|
23
|
+
y.should be(0)
|
24
|
+
z.should be(0)
|
25
|
+
|
26
|
+
x,y,z = normalize 0,1,0
|
27
|
+
x.should be(0)
|
28
|
+
y.should be(1)
|
29
|
+
z.should be(0)
|
30
|
+
|
31
|
+
x,y,z = normalize 0,0,1
|
32
|
+
x.should be(0)
|
33
|
+
y.should be(0)
|
34
|
+
z.should be(1)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should correctly normalize vector" do
|
38
|
+
x,y,z = normalize 0.5,0.5,0.5
|
39
|
+
(x - 0.577350269189626).should < 0.000000000000001
|
40
|
+
(y - 0.577350269189626).should < 0.000000000000001
|
41
|
+
(z - 0.577350269189626).should < 0.000000000000001
|
42
|
+
|
43
|
+
x,y,z = normalize 0.75,0.6,0.12
|
44
|
+
(x - 0.77484465921718).should < 0.000000000000001
|
45
|
+
(y - 0.619875727373744).should < 0.000000000000001
|
46
|
+
(z - 0.123975145474749).should < 0.000000000000001
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "orthogonal?" do
|
52
|
+
it "should return true for orthoginal vectors" do
|
53
|
+
orthogonal?(1,0,0, 0,1,0).should == true
|
54
|
+
orthogonal?(1,0,0, 0,0,1).should == true
|
55
|
+
orthogonal?(0,1,0, 0,0,1).should == true
|
56
|
+
|
57
|
+
orthogonal?(-1,0,0, 0,-1,0).should == true
|
58
|
+
orthogonal?(1,0,0, 0,0,-1).should == true
|
59
|
+
orthogonal?(0,-1,0, 0,0,1).should == true
|
60
|
+
|
61
|
+
orthogonal?(1,3,2, 3,-1,0).should == true
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should return false for nonorthoginal vectors" do
|
65
|
+
orthogonal?(1,0,0, -1,0,0).should == false
|
66
|
+
orthogonal?(1,0,0, 1,0,0).should == false
|
67
|
+
orthogonal?(0.5,0.14,0.98, 7.1,-6.5,0).should == false
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe Float do
|
72
|
+
it "should correctly round to specified percision" do
|
73
|
+
5.12345.round_to(1).should == 5.1
|
74
|
+
-5.12345.round_to(2).should == -5.12
|
75
|
+
5.12345.round_to(6).should == 5.12345
|
76
|
+
end
|
77
|
+
end
|
data/spec/dsl_spec.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# dsl module tests
|
2
|
+
#
|
3
|
+
# Copyright (C) 2010 Mohammed Morsi <movitto@yahoo.com>
|
4
|
+
# Licensed under the AGPLv3+ http://www.gnu.org/licenses/agpl.txt
|
5
|
+
|
6
|
+
dir = File.dirname(__FILE__)
|
7
|
+
require dir + '/spec_helper'
|
8
|
+
|
9
|
+
SIMRPC_SPEC = dir + '/../conf/motel-schema.xml'
|
10
|
+
|
11
|
+
describe "Motel::dsl" do
|
12
|
+
|
13
|
+
it "should permit simple connections" do
|
14
|
+
# setup simrpc server endpoint
|
15
|
+
server = Motel::Server.new :schema_file => SIMRPC_SPEC
|
16
|
+
|
17
|
+
# use dsl to connect to server and issue a few requests
|
18
|
+
connect :schema_file => SIMRPC_SPEC do |client|
|
19
|
+
location_id = 100
|
20
|
+
client.create_location(location_id).should be(true)
|
21
|
+
loc = client.get_location(location_id)
|
22
|
+
loc.should_not be_nil
|
23
|
+
loc.id.should be(location_id)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# location module tests
|
2
|
+
#
|
3
|
+
# Copyright (C) 2010 Mohammed Morsi <movitto@yahoo.com>
|
4
|
+
# Licensed under the AGPLv3+ http://www.gnu.org/licenses/agpl.txt
|
5
|
+
|
6
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
7
|
+
|
8
|
+
describe Location do
|
9
|
+
|
10
|
+
it "should successfully accept and set location params" do
|
11
|
+
parent = Location.new
|
12
|
+
location = Location.new :id => 1, :parent_id => 2, :parent => parent, :x => 3, :y => 4, :z => 5
|
13
|
+
location.id.should == 1
|
14
|
+
location.parent_id.should == 2
|
15
|
+
location.x.should == 3
|
16
|
+
location.y.should == 4
|
17
|
+
location.z.should == 5
|
18
|
+
location.parent.should == parent
|
19
|
+
location.children.should == []
|
20
|
+
location.movement_callbacks.should == []
|
21
|
+
location.movement_strategy.should == MovementStrategies::Stopped.instance
|
22
|
+
|
23
|
+
ms = TestMovementStrategy.new
|
24
|
+
location = Location.new :movement_strategy => ms
|
25
|
+
location.movement_strategy.should == ms
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should default to origin coordinates" do
|
29
|
+
loc = Location.new
|
30
|
+
loc.x.should == 0
|
31
|
+
loc.y.should == 0
|
32
|
+
loc.z.should == 0
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should be updatable given another location to copy" do
|
36
|
+
p1 = Location.new
|
37
|
+
p2 = Location.new
|
38
|
+
|
39
|
+
orig = Location.new :x => 1, :y => 2, :movement_strategy => 'foobar', :parent_id => 5, :parent => p1
|
40
|
+
new = Location.new :x => 5, :movement_strategy => 'foomoney', :parent_id => 10, :parent => p2
|
41
|
+
orig.update(new)
|
42
|
+
orig.x.should be(5)
|
43
|
+
orig.y.should be(0)
|
44
|
+
orig.y.should be(0)
|
45
|
+
orig.movement_strategy.should == "foomoney"
|
46
|
+
orig.parent_id.should be(10)
|
47
|
+
orig.parent.should be(p2)
|
48
|
+
|
49
|
+
orig.y = 6
|
50
|
+
new.y = nil
|
51
|
+
orig.update(new)
|
52
|
+
orig.y.should be(6)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "retrieve root location" do
|
56
|
+
ggp = Location.new
|
57
|
+
gp = Location.new :parent => ggp
|
58
|
+
p = Location.new :parent => gp
|
59
|
+
l = Location.new :parent => p
|
60
|
+
c = Location.new :parent => l
|
61
|
+
gc = Location.new :parent => c
|
62
|
+
|
63
|
+
gp.root.should == ggp
|
64
|
+
p.root.should == ggp
|
65
|
+
l.root.should == ggp
|
66
|
+
c.root.should == ggp
|
67
|
+
gc.root.should == ggp
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should provide means to traverse all descendants, invoking optional block arg" do
|
71
|
+
greatgrandparent = Location.new
|
72
|
+
grandparent = Location.new
|
73
|
+
greatgrandparent.children.push grandparent
|
74
|
+
grampy = Location.new
|
75
|
+
greatgrandparent.children.push grampy
|
76
|
+
parent = Location.new
|
77
|
+
grandparent.children.push parent
|
78
|
+
parent2 = Location.new
|
79
|
+
grandparent.children.push parent2
|
80
|
+
child1 = Location.new
|
81
|
+
parent.children.push child1
|
82
|
+
child2 = Location.new
|
83
|
+
parent.children.push child2
|
84
|
+
|
85
|
+
i = 0
|
86
|
+
greatgrandparent.traverse_descendants { |desc|
|
87
|
+
i += 1
|
88
|
+
}
|
89
|
+
|
90
|
+
i.should == 6
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should return total position from root origin" do
|
94
|
+
grandparent = Location.new
|
95
|
+
parent = Location.new :parent => grandparent,
|
96
|
+
:x => 14,
|
97
|
+
:y => 24,
|
98
|
+
:z => 42
|
99
|
+
child = Location.new :parent => parent,
|
100
|
+
:x => 123,
|
101
|
+
:y => -846,
|
102
|
+
:z => -93
|
103
|
+
|
104
|
+
child.total_x.should == 14 + 123
|
105
|
+
child.total_y.should == 24 - 846
|
106
|
+
child.total_z.should == 42 - 93
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# elliptical movement strategy tests
|
2
|
+
#
|
3
|
+
# Copyright (C) 2009 Mohammed Morsi <movitto@yahoo.com>
|
4
|
+
# See COPYING for the License of this software
|
5
|
+
|
6
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
7
|
+
|
8
|
+
describe "Motel::MovementStrategies::Elliptical" do
|
9
|
+
|
10
|
+
it "should successfully accept and set elliptical params" do
|
11
|
+
elliptical = Elliptical.new :relative_to => Elliptical::RELATIVE_TO_CENTER, :speed => 5,
|
12
|
+
:eccentricity => 0.5, :semi_latus_rectum => 10,
|
13
|
+
:direction_major_x => 1, :direction_major_y => 3, :direction_major_z => 2,
|
14
|
+
:direction_minor_x => 3, :direction_minor_y => -1, :direction_minor_z => 0
|
15
|
+
|
16
|
+
# the orthogonal direction vectors get normalized
|
17
|
+
(elliptical.direction_major_x - 0.267261241912424).abs.should < 0.0000000001
|
18
|
+
(elliptical.direction_major_y - 0.801783725737273).abs.should < 0.0000000001
|
19
|
+
(elliptical.direction_major_z - 0.534522483824849).abs.should < 0.0000000001
|
20
|
+
(elliptical.direction_minor_x - 0.948683298050514).abs.should < 0.0000000001
|
21
|
+
(elliptical.direction_minor_y - -0.316227766016838).abs.should < 0.0000000001
|
22
|
+
elliptical.direction_minor_z.should == 0
|
23
|
+
|
24
|
+
elliptical.speed.should == 5
|
25
|
+
elliptical.relative_to.should == Elliptical::RELATIVE_TO_CENTER
|
26
|
+
elliptical.eccentricity.should == 0.5
|
27
|
+
elliptical.semi_latus_rectum.should == 10
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should default to standard cartesian direction axis" do
|
31
|
+
elliptical = Elliptical.new
|
32
|
+
elliptical.direction_major_x.should == 1
|
33
|
+
elliptical.direction_major_y.should == 0
|
34
|
+
elliptical.direction_major_z.should == 0
|
35
|
+
elliptical.direction_minor_x.should == 0
|
36
|
+
elliptical.direction_minor_y.should == 1
|
37
|
+
elliptical.direction_minor_z.should == 0
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should raise exception if direction vectors are orthogonal" do
|
41
|
+
lambda {
|
42
|
+
elliptical = Elliptical.new :direction_major_x => 0.75, :direction_major_y => -0.33, :direction_major_z => -0.21,
|
43
|
+
:direction_minor_x => -0.41, :direction_minor_y => 0, :direction_minor_z => 0.64
|
44
|
+
}.should raise_error(InvalidMovementStrategy, "elliptical direction vectors not orthogonal")
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
it "should move location correctly" do
|
49
|
+
elliptical = Elliptical.new(:step_delay => 5,
|
50
|
+
:relative_to => Elliptical::RELATIVE_TO_CENTER,
|
51
|
+
:speed => 1.57,
|
52
|
+
:eccentricity => 0, # circle
|
53
|
+
:semi_latus_rectum => 1,
|
54
|
+
:direction_major_x => 1,
|
55
|
+
:direction_major_y => 0,
|
56
|
+
:direction_major_z => 0,
|
57
|
+
:direction_minor_x => 0,
|
58
|
+
:direction_minor_y => 1,
|
59
|
+
:direction_minor_z => 0)
|
60
|
+
|
61
|
+
parent = Location.new
|
62
|
+
x = 1
|
63
|
+
y = z = 0
|
64
|
+
location = Location.new(:parent => parent,
|
65
|
+
:movement_strategy => elliptical,
|
66
|
+
:x => x, :y => y, :z => z)
|
67
|
+
|
68
|
+
# move and validate
|
69
|
+
elliptical.move location, 1
|
70
|
+
(0 - location.x).abs.round_to(2).should == 0
|
71
|
+
(1 - location.y).abs.round_to(2).should == 0
|
72
|
+
(0 - location.z).abs.round_to(2).should == 0
|
73
|
+
|
74
|
+
elliptical.move location, 1
|
75
|
+
(-1 - location.x).abs.round_to(2).should == 0
|
76
|
+
(0 - location.y).abs.round_to(2).should == 0
|
77
|
+
(0 - location.z).abs.round_to(2).should == 0
|
78
|
+
|
79
|
+
elliptical.move location, 1
|
80
|
+
(0 - location.x).abs.round_to(2).should == 0
|
81
|
+
(-1 - location.y).abs.round_to(2).should == 0
|
82
|
+
(0 - location.z).abs.round_to(2).should == 0
|
83
|
+
|
84
|
+
elliptical.move location, 1
|
85
|
+
(1 - location.x).abs.round_to(2).should == 0
|
86
|
+
(0 - location.y).abs.round_to(2).should == 0
|
87
|
+
(0 - location.z).abs.round_to(2).should == 0
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# linear movement strategy tests
|
2
|
+
#
|
3
|
+
# Copyright (C) 2009 Mohammed Morsi <movitto@yahoo.com>
|
4
|
+
# See COPYING for the License of this software
|
5
|
+
|
6
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
7
|
+
|
8
|
+
describe "Motel::MovementStrategies::Linear" do
|
9
|
+
|
10
|
+
it "should successfully accept and set linear params" do
|
11
|
+
linear = Linear.new :direction_vector_x => 1, :direction_vector_y => 2, :direction_vector_z => 3, :speed => 5
|
12
|
+
|
13
|
+
# ensure linear vector gets automatically normailized
|
14
|
+
dx,dy,dz = normalize 1,2,3
|
15
|
+
linear.direction_vector_x.should == dx
|
16
|
+
linear.direction_vector_y.should == dy
|
17
|
+
linear.direction_vector_z.should == dz
|
18
|
+
|
19
|
+
linear.speed.should == 5
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
it "should move location correctly" do
|
24
|
+
linear = Linear.new :step_delay => 5, :speed => 20,
|
25
|
+
:direction_vector_x => 5, :direction_vector_y => 5, :direction_vector_z => 5
|
26
|
+
dx,dy,dz = linear.direction_vector_x, linear.direction_vector_y, linear.direction_vector_z
|
27
|
+
|
28
|
+
parent = Location.new
|
29
|
+
x = y = z = 20
|
30
|
+
location = Location.new(:parent => parent,
|
31
|
+
:movement_strategy => linear,
|
32
|
+
:x => x, :y => y, :z => z)
|
33
|
+
|
34
|
+
# move and validate
|
35
|
+
linear.move location, 1
|
36
|
+
location.x.should == x + dx * linear.speed
|
37
|
+
location.y.should == y + dy * linear.speed
|
38
|
+
location.z.should == z + dz * linear.speed
|
39
|
+
|
40
|
+
x = location.x
|
41
|
+
y = location.y
|
42
|
+
z = location.z
|
43
|
+
|
44
|
+
linear.move location, 5
|
45
|
+
location.x.should == x + dx * linear.speed * 5
|
46
|
+
location.y.should == y + dy * linear.speed * 5
|
47
|
+
location.z.should == z + dz * linear.speed * 5
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# stopped movement strategy tests
|
2
|
+
#
|
3
|
+
# Copyright (C) 2009 Mohammed Morsi <movitto@yahoo.com>
|
4
|
+
# See COPYING for the License of this software
|
5
|
+
|
6
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
7
|
+
|
8
|
+
describe "Motel::MovementStrategies::Stopped" do
|
9
|
+
|
10
|
+
it "should not move location" do
|
11
|
+
# setup test
|
12
|
+
stopped = Stopped.instance
|
13
|
+
parent = Location.new
|
14
|
+
x = 50
|
15
|
+
y = 100
|
16
|
+
z = 200
|
17
|
+
location = Location.new(:parent => parent,
|
18
|
+
:movement_strategy => stopped,
|
19
|
+
:x => 50, :y => 100, :z => 200)
|
20
|
+
|
21
|
+
# make sure location does not move
|
22
|
+
stopped.move location, 10
|
23
|
+
location.x.should == x
|
24
|
+
location.y.should == y
|
25
|
+
location.z.should == z
|
26
|
+
|
27
|
+
stopped.move location, 50
|
28
|
+
location.x.should == x
|
29
|
+
location.y.should == y
|
30
|
+
location.z.should == z
|
31
|
+
|
32
|
+
stopped.move location, 0
|
33
|
+
location.x.should == x
|
34
|
+
location.y.should == y
|
35
|
+
location.z.should == z
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# movement strategy module tests
|
2
|
+
#
|
3
|
+
# Copyright (C) 2010 Mohammed Morsi <movitto@yahoo.com>
|
4
|
+
# Licensed under the AGPLv3+ http://www.gnu.org/licenses/agpl.txt
|
5
|
+
|
6
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
7
|
+
|
8
|
+
describe MovementStrategy do
|
9
|
+
|
10
|
+
it "should successfully accept and set movement strategy params" do
|
11
|
+
ms = MovementStrategy.new :step_delay => 10
|
12
|
+
ms.step_delay.should == 10
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should default to no movement" do
|
16
|
+
loc = Location.new :x => 100, :y => -200, :z => 300
|
17
|
+
ms = MovementStrategy.new
|
18
|
+
ms.move loc, 2000
|
19
|
+
loc.x.should == 100
|
20
|
+
loc.y.should == -200
|
21
|
+
loc.z.should == 300
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
data/spec/runner_spec.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# runner module tests
|
2
|
+
#
|
3
|
+
# Copyright (C) 2010 Mohammed Morsi <movitto@yahoo.com>
|
4
|
+
# Licensed under the AGPLv3+ http://www.gnu.org/licenses/agpl.txt
|
5
|
+
|
6
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
7
|
+
|
8
|
+
describe Runner do
|
9
|
+
|
10
|
+
it "manage array of locations to be run" do
|
11
|
+
loc = Location.new
|
12
|
+
Runner.instance.locations.clear
|
13
|
+
Runner.instance.locations.should == []
|
14
|
+
Runner.instance.run loc
|
15
|
+
Runner.instance.locations.should == [loc]
|
16
|
+
Runner.instance.locations.clear
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should run managed locations" do
|
20
|
+
loc1 = Location.new :movement_strategy => TestMovementStrategy.new
|
21
|
+
loc2 = Location.new :movement_strategy => TestMovementStrategy.new
|
22
|
+
Runner.instance.locations.clear
|
23
|
+
Runner.instance.run loc1
|
24
|
+
Runner.instance.run loc2
|
25
|
+
Runner.instance.locations.size.should == 2
|
26
|
+
|
27
|
+
Runner.instance.start :async => true, :num_threads => 10
|
28
|
+
Runner.instance.thread_pool.should_not == nil
|
29
|
+
Runner.instance.thread_pool.max_size.should == 10
|
30
|
+
Runner.instance.terminate.should == false
|
31
|
+
|
32
|
+
# TODO should we sleep here for a fixed time, to allow
|
33
|
+
# move to be called multiple times ?
|
34
|
+
|
35
|
+
Runner.instance.stop
|
36
|
+
Runner.instance.terminate.should == true
|
37
|
+
|
38
|
+
Runner.instance.join
|
39
|
+
Runner.instance.run_thread.should == nil
|
40
|
+
|
41
|
+
loc1.movement_strategy.times_moved.should be > 0
|
42
|
+
loc2.movement_strategy.times_moved.should be > 0
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
data/spec/simrpc_spec.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# simrpc module tests
|
2
|
+
#
|
3
|
+
# Copyright (C) 2010 Mohammed Morsi <movitto@yahoo.com>
|
4
|
+
# Licensed under the AGPLv3+ http://www.gnu.org/licenses/agpl.txt
|
5
|
+
|
6
|
+
dir = File.dirname(__FILE__)
|
7
|
+
require dir + '/spec_helper'
|
8
|
+
|
9
|
+
describe "Motel::Simrpc" do
|
10
|
+
|
11
|
+
before(:each) do
|
12
|
+
# setup simrpc endpoints
|
13
|
+
@server = Motel::Server.new :schema_file => dir + '/../conf/motel-schema.xml'
|
14
|
+
@client = Motel::Client.new :schema_file => dir + '/../conf/motel-schema.xml'
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should fail to retreive invalid location" do
|
18
|
+
@client.get_location(-500).should be_nil
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should permit location creation and retrieval" do
|
22
|
+
locations = Runner.instance.locations.size
|
23
|
+
location_id = 10
|
24
|
+
@client.create_location(location_id).should be(true)
|
25
|
+
Runner.instance.locations.size.should == locations + 1
|
26
|
+
|
27
|
+
loc = @client.get_location(location_id)
|
28
|
+
loc.should_not be_nil
|
29
|
+
loc.id.should be(location_id)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should permit updating a location" do
|
33
|
+
location_id = 20
|
34
|
+
@client.create_location(location_id).should be(true)
|
35
|
+
@client.update_location(Location.new(:id => location_id, :x => 150, :y => 300, :z => -600)).should be(true)
|
36
|
+
|
37
|
+
loc = @client.get_location(location_id)
|
38
|
+
loc.should_not be_nil
|
39
|
+
loc.x.should be(150)
|
40
|
+
loc.y.should be(300)
|
41
|
+
loc.z.should be(-600)
|
42
|
+
|
43
|
+
loc = @client.request :get_location, location_id
|
44
|
+
loc.should_not be_nil
|
45
|
+
loc.x.should be(150)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should permit receiving location updates" do
|
49
|
+
# start the runner here, to actual move location / process callbacks
|
50
|
+
Runner.instance.start :async => true
|
51
|
+
|
52
|
+
# create the location
|
53
|
+
location_id = 30
|
54
|
+
@client.create_location(location_id).should be(true)
|
55
|
+
|
56
|
+
## set a linear movement strategy
|
57
|
+
location = Location.new
|
58
|
+
location.id = location_id
|
59
|
+
location.movement_strategy = Linear.new(:step_delay => 1,
|
60
|
+
:speed => 15,
|
61
|
+
:direction_vector_x => 1,
|
62
|
+
:direction_vector_y => 0,
|
63
|
+
:direction_vector_z => 0)
|
64
|
+
@client.update_location(location).should be(true)
|
65
|
+
|
66
|
+
times_moved = 0
|
67
|
+
|
68
|
+
# handle location_moved method
|
69
|
+
@client.on_location_received = lambda { |location|
|
70
|
+
times_moved += 1
|
71
|
+
}
|
72
|
+
|
73
|
+
## subscribe to updates
|
74
|
+
@client.subscribe_to_location(location_id).should be(true)
|
75
|
+
|
76
|
+
## delay briefly allowing for updates
|
77
|
+
sleep 5
|
78
|
+
|
79
|
+
times_moved.should be > 0
|
80
|
+
|
81
|
+
# stop the runner
|
82
|
+
Runner.instance.stop
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# loads and runs all tests for the motel project
|
2
|
+
#
|
3
|
+
# Copyright (C) 2010 Mohammed Morsi <movitto@yahoo.com>
|
4
|
+
# Licensed under the AGPLv3+ http://www.gnu.org/licenses/agpl.txt
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require 'spec'
|
8
|
+
|
9
|
+
CURRENT_DIR=File.dirname(__FILE__)
|
10
|
+
$: << File.expand_path(CURRENT_DIR + "/../lib")
|
11
|
+
|
12
|
+
require 'motel'
|
13
|
+
include Motel
|
14
|
+
include Motel::MovementStrategies
|
15
|
+
|
16
|
+
class TestMovementStrategy < MovementStrategy
|
17
|
+
attr_accessor :times_moved
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
@times_moved = 0
|
21
|
+
end
|
22
|
+
|
23
|
+
def move(loc, elapsed_time)
|
24
|
+
@times_moved += 1
|
25
|
+
end
|
26
|
+
end
|