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.
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