motel 0.2 → 0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/README.rdoc +35 -0
  2. data/Rakefile +48 -0
  3. data/bin/clients/simple/main.rb +131 -0
  4. data/bin/server/main.rb +61 -0
  5. data/conf/motel-schema.xml +72 -0
  6. data/lib/motel/common.rb +35 -11
  7. data/lib/motel/dsl.rb +12 -0
  8. data/lib/motel/exceptions.rb +14 -0
  9. data/lib/motel/location.rb +100 -0
  10. data/lib/motel/{models → movement_strategies}/elliptical.rb +51 -89
  11. data/lib/motel/movement_strategies/linear.rb +54 -0
  12. data/lib/motel/movement_strategies/stopped.rb +18 -0
  13. data/lib/motel/movement_strategy.rb +29 -0
  14. data/lib/motel/runner.rb +94 -108
  15. data/lib/motel/simrpc.rb +131 -0
  16. data/lib/motel/thread_pool.rb +51 -0
  17. data/lib/motel.rb +9 -5
  18. data/spec/common_spec.rb +77 -0
  19. data/spec/dsl_spec.rb +27 -0
  20. data/spec/location_spec.rb +109 -0
  21. data/spec/movement_strategies/elliptical_spec.rb +90 -0
  22. data/spec/movement_strategies/linear_spec.rb +51 -0
  23. data/spec/movement_strategies/stopped_spec.rb +39 -0
  24. data/spec/movement_strategy_spec.rb +24 -0
  25. data/spec/runner_spec.rb +45 -0
  26. data/spec/simrpc_spec.rb +85 -0
  27. data/spec/spec_helper.rb +26 -0
  28. metadata +36 -34
  29. data/README +0 -0
  30. data/conf/amqp.yml +0 -13
  31. data/conf/database.yml +0 -41
  32. data/db/migrate/001_create_locations_and_movement_strategies.rb +0 -45
  33. data/db/migrate/002_create_linear_movement_strategy.rb +0 -23
  34. data/db/migrate/003_create_elliptical_movement_strategy.rb +0 -52
  35. data/lib/motel/loader.rb +0 -47
  36. data/lib/motel/models/linear.rb +0 -76
  37. data/lib/motel/models/location.rb +0 -109
  38. data/lib/motel/models/movement_strategy.rb +0 -82
  39. 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) 2009 Mohammed Morsi <movitto@yahoo.com>
4
- # See COPYING for the License of this software
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/conf'
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
- Dir[lib + '/motel/models/*.rb'].each { |model| require model }
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 }
@@ -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
@@ -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
@@ -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
@@ -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