motel 0.2 → 0.3
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/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
|