ant_hill 0.3.1

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.
@@ -0,0 +1,4 @@
1
+ module AntHill
2
+ # Version of gem
3
+ VERSION = "0.3.1"
4
+ end
@@ -0,0 +1,48 @@
1
+ require 'ant_hill'
2
+
3
+ namespace :ant_hill do
4
+ task :add_colony do
5
+ host = ENV['drb_host'] || 'localhost'
6
+ AntHill::Queen.create_colony ARGV[1..-1], host
7
+ end
8
+
9
+ task :kill_colony do
10
+ host = ENV['drb_host'] || 'localhost'
11
+ AntHill::Queen.kill_colony ARGV[1..-1], host
12
+ end
13
+
14
+ task :monitor do
15
+ queen = AntHill::Queen.drb_queen(host)
16
+ while true
17
+ sleep 2
18
+ print "\e[2J\e[f"
19
+ puts "Creep size: #{queen.creeps.size}"
20
+ puts "Ants left: #{queen.size}"
21
+ queen.creeps.each{|creep|
22
+ puts creep.to_s
23
+ }
24
+ end
25
+ end
26
+
27
+ task :execute_each do
28
+ threads = []
29
+ AntHill::Queen.creeps(host).each{|creep|
30
+ threads << Thread.new do
31
+ creep.exec!(ENV['command'])
32
+ end
33
+ }
34
+ threads.each{ |t| t.join}
35
+ end
36
+
37
+ task :suspend_queen do
38
+ AntHill::Queen.drb_queen(host).suspend
39
+ end
40
+
41
+ task :release_queen do
42
+ AntHill::Queen.drb_queen(host).release
43
+ end
44
+
45
+ def host
46
+ ENV['drb_host'] || 'localhost'
47
+ end
48
+ end
@@ -0,0 +1,118 @@
1
+ require 'spec_helper'
2
+
3
+ module AntHill
4
+ describe AntColony do
5
+ let(:params){ {"type" => "type", "a" => 1, "b" => 2 } }
6
+ let(:colony){ AntColony.new(params) }
7
+
8
+ before :each do
9
+ config = double("config")
10
+ config.stub(:creep_modifier_class){|type| "Creep modifier for #{type}" }
11
+ config.stub(:log_level){ :log_level }
12
+ config.stub(:log_dir){ log_dir }
13
+ config.stub(:init_time){ Time.now}
14
+ Configuration.stub(:config){config}
15
+
16
+ logger = double("logger")
17
+ Log.stub(:logger_for){logger}
18
+ end
19
+
20
+ context "#initialize" do
21
+ it "should store params" do
22
+ colony.params.should eql(params)
23
+ end
24
+ end
25
+
26
+ context "#type" do
27
+ it "should return type from params" do
28
+ colony.type.should eql("type")
29
+ end
30
+ end
31
+
32
+ context "#creep_modifier_class" do
33
+ it "should return creep modifier class for type" do
34
+ Configuration.config.should_receive(:creep_modifier_class).with("type").and_return("Creep modifier for type")
35
+ colony.creep_modifier_class.should eql("Creep modifier for type")
36
+ end
37
+
38
+ it "should log error if no such type defined" do
39
+ test_params = params
40
+ test_params['type']="wrong_type"
41
+
42
+ colony = AntColony.new(params)
43
+ Configuration.config.should_receive(:creep_modifier_class).with("wrong_type").and_return(nil)
44
+ Log.logger_for.should_receive(:error).with("Colony will die without creep modifier ;(")
45
+ colony.creep_modifier_class.should be_nil
46
+ end
47
+ end
48
+
49
+ context "#spoiled?" do
50
+ it "should be spoiled if no creep modifier class was set" do
51
+ test_params = params
52
+ test_params['type']="wrong_type"
53
+ colony = AntColony.new(params)
54
+ colony.spoiled?.should be_true
55
+ end
56
+ end
57
+
58
+ context "#get_ants" do
59
+ it "should add self params to all ants " do
60
+ colony.stub(:search_ants){ [{:param1 => 1, :param2 => 2},{ :param1 => 3, :param2 => 2}] }
61
+ ants = colony.get_ants
62
+ ants.should_not be_empty
63
+ ants.each{|ant|
64
+ ant.params['type'].should eql('type')
65
+ ant.params['a'].should eql(1)
66
+ ant.params['b'].should eql(2)
67
+ ant.params[:param2].should eql(2)
68
+ }
69
+ ants[0].params[:param1].should eql(1)
70
+ ants[1].params[:param1].should eql(3)
71
+ end
72
+
73
+ it "should call after_search" do
74
+ colony.stub(:search_ants){ [{:param1 => 1, :param2 => 2},{ :param1 => 3, :param2 => 2}] }
75
+ colony.should_receive(:after_search)
76
+ colony.get_ants
77
+ end
78
+
79
+ it "should log error if something's happened" do
80
+ colony.stub(:search_ants){ raise }
81
+ Log.logger_for.should_receive(:error).with(/Error while processing search ants for colony/)
82
+ ants = colony.get_ants
83
+ end
84
+ end
85
+
86
+ context "#is_it_me?" do
87
+ it "should return true if all params matches" do
88
+ colony.is_it_me?({"type"=> "type", "a" => 1}).should be_true
89
+ end
90
+ it "should return false if at least one param doesn't match" do
91
+ colony.is_it_me?({"type"=> "type", "a" => 2}).should be_false
92
+ end
93
+ end
94
+
95
+ context "#not_finished" do
96
+ it "should return not finished ants" do
97
+ ant1 = double("ant1")
98
+ ant2 = double("ant2")
99
+ ant3 = double("ant3")
100
+ ant4 = double("ant4")
101
+ ant1.stub(:finished?){true}
102
+ ant2.stub(:finished?){false}
103
+ ant3.stub(:finished?){true}
104
+ ant4.stub(:finished?){true}
105
+ colony.stub(:ants){ [ant1, ant2, ant3, ant4] }
106
+ colony.not_finished.should eql([ant1, ant3, ant4])
107
+ end
108
+
109
+ end
110
+ context "#type" do
111
+ it "should return type from params" do
112
+ colony.params['type'].should eql("type")
113
+ end
114
+ end
115
+
116
+
117
+ end
118
+ end
@@ -0,0 +1,101 @@
1
+ require 'spec_helper'
2
+
3
+ module AntHill
4
+ describe Ant do
5
+ before :each do
6
+ config = double("config")
7
+ config.stub(:creep_modifier_class){|type| "Creep modifier for #{type}" }
8
+ config.stub(:log_level){ :log_level }
9
+ config.stub(:log_dir){ log_dir }
10
+ config.stub(:init_time){ Time.at(0)}
11
+ Configuration.stub(:config){config}
12
+
13
+ logger = double("logger")
14
+ Log.stub(:logger_for){logger}
15
+ end
16
+
17
+ let(:ant_colony){
18
+ ac = double("ant_colony")
19
+ ac.stub(:type){ "type" }
20
+ ac.stub(:params){ {"type" => "type", "a" => 1, "b" => 2} }
21
+ cmc = double(:creep_modifier_class)
22
+ cm = double(:creep_modifier)
23
+ cmc.stub(:change_time_for_param){|param|
24
+ case param
25
+ when 'a' then 1
26
+ when 'b' then 2
27
+ else
28
+ 0
29
+ end
30
+
31
+ }
32
+ cmc.stub(:new){ cm}
33
+ ac.stub(:creep_modifier_class){cmc}
34
+ ac.stub(:change_time_for_param){|param|
35
+ case param
36
+ when 'a' then 1
37
+ when 'b' then 2
38
+ else
39
+ 0
40
+ end
41
+
42
+ }
43
+ ac
44
+ }
45
+
46
+ let(:ant){Ant.new( { "param1" => "params", "param2" => "param2"}, ant_colony )}
47
+
48
+ context "#initialize" do
49
+ it "should have colony" do
50
+ ant.colony.should eql(ant_colony)
51
+ end
52
+ it "should merge colony and self params" do
53
+ ant.params.should eql({ "type" => "type", "a" => 1, "b" => 2, "param1" => "params", "param2" => "param2" })
54
+ end
55
+ it "should have status not_started" do
56
+ ant.status.should eql(:not_started)
57
+ end
58
+ end
59
+
60
+ context "#to_s" do
61
+ it "should return string of params" do
62
+ ant.to_s.should eql(ant.params.inspect.to_s)
63
+ end
64
+ end
65
+
66
+ context "#change_status" do
67
+ it "should set status" do
68
+ ant.change_status(:started)
69
+ ant.status.should eql(:started)
70
+ end
71
+ end
72
+
73
+ context "#priority" do
74
+ it "should have higher priority for matches params" do
75
+ ant.priority({}).should < ant.priority({"a" => 1})
76
+ ant.priority({"a" => 1}).should < ant.priority({"a" => 1, "b" => 2})
77
+ end
78
+
79
+ it "should increase priority on sum values defined for param in change_time_for_param method" do
80
+ ant.priority({ "a" => 1 }).should be_within(0.0001).of( ant.priority({"a" => 0}) + 1 )
81
+ ant.priority({ "b" => 2 }).should be_within(0.0001).of( ant.priority({"b" => 0}) + 2 )
82
+
83
+ end
84
+ it "should return same value for same params " do
85
+ ant.priority({ "b" => 2 }).should be_within(0.0001).of( ant.priority({"b" => 2}) )
86
+ end
87
+
88
+ end
89
+
90
+ context "#finished?" do
91
+ it "should return false if ant status is finished" do
92
+ ant.stub(:status){:in_progress}
93
+ ant.finished?.should be_false
94
+ end
95
+ it "should return true if ant status is finished" do
96
+ ant.stub(:status){:finished}
97
+ ant.finished?.should be_true
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,201 @@
1
+ require 'spec_helper'
2
+ module AntHill
3
+ describe Configuration do
4
+
5
+ let(:hash){
6
+ {
7
+ 'basedir' => "a",
8
+ 'lib_path' => 'b',
9
+ 'sleep_interval' => 1,
10
+ 'log_dir' => 'some_dir',
11
+ 'log_level' => ':error',
12
+ 'types' => {
13
+ 'a' => {
14
+ 'ant_colony_class' => 'String',
15
+ 'creep_modifier_class' => 'Object'
16
+ },
17
+ 'b' => {
18
+ 'ant_colony_class' => 'Hash',
19
+ 'creep_modifier_class' => 'String'
20
+ },
21
+ 'c' => {
22
+ 'ant_colony_class' => 'SomeClass',
23
+ 'creep_modifier_class' => 'SomeOtherClass'
24
+ }
25
+ },
26
+ 'default_type' => 'a',
27
+ 'log_path' => 'log_path',
28
+ 'creeps' => [
29
+ { 'name' => 1, 'host' => 'host', 'login' => 'login', 'password' => 'password'},
30
+ { 'name' => 2, 'host' => 'host2', 'login' => 'login2', 'password' => 'password2'}
31
+ ]
32
+
33
+ }
34
+ }
35
+ before(:each) do
36
+ YAML.stub(:load_file) {|filename| hash }
37
+ Time.stub(:now) { Time.at(0) }
38
+ File.stub(:join) { 'rubygems'}
39
+ logger = double("logger")
40
+ Log.stub(:logger_for){logger}
41
+ end
42
+
43
+ let(:config) { Configuration.new }
44
+
45
+ let(:config_parsed){
46
+ c = Configuration.new
47
+ c.parse_yaml("config.yml")
48
+ c
49
+ }
50
+
51
+ context "#initialize" do
52
+ it "should set init_time" do
53
+ config.init_time == Time.at(0)
54
+ end
55
+ end
56
+
57
+ context "#parse_yaml" do
58
+ it "should fail if file not exists" do
59
+ STDERR.stub(:puts)
60
+ STDERR.should_receive(:puts).with(/Couldn't find config file/)
61
+ YAML.stub(:load_file){raise}
62
+ lambda{ config.parse_yaml("config.yml") }.should raise_error(SystemExit)
63
+ end
64
+
65
+ it "should load configuration" do
66
+ config.parse_yaml("config.yml")
67
+ config.instance_variable_get("@configuration").should_not eql({})
68
+ end
69
+ end
70
+
71
+ context "#require_libs" do
72
+ it "should require file base_dir+libpath" do
73
+ config_parsed.stub(:require){nil}
74
+ config_parsed.should_receive(:require).with("rubygems")
75
+ config_parsed.require_libs
76
+ end
77
+ it "should require file base_dir+libpath" do
78
+ config_parsed.stub(:require){ raise LoadError }
79
+ config_parsed.should_receive(:require).with("rubygems")
80
+ STDERR.should_receive(:puts).with(/Configuration file is invalid! No such file exists rubygems/)
81
+ config_parsed.require_libs
82
+ end
83
+ end
84
+
85
+ context "#validate" do
86
+
87
+ context "with valid config" do
88
+ it "should not exit if config is valid" do
89
+ lambda{config_parsed.validate}.should_not raise_error(SystemExit)
90
+ end
91
+ end
92
+ context "with invalid config" do
93
+ before(:each) do
94
+ STDERR.stub(:puts)
95
+ end
96
+ %w{ basedir lib_path types creeps log_dir log_level }.each do |key|
97
+ it "should log error and exit if #{key} unset" do
98
+ new_hash = hash.clone
99
+ new_hash.delete(key)
100
+ YAML.stub(:load_file){|filename| new_hash }
101
+ c = Configuration.new
102
+ c.parse_yaml("config.yml")
103
+ STDERR.should_receive(:puts).with(/Configuration file is invalid! Pls. define .* keys in it/)
104
+ lambda{c.validate}.should raise_error(SystemExit)
105
+ end
106
+ end
107
+
108
+ %w{ types creeps }.each do |key|
109
+ it "should log error and exit #{key} has no children" do
110
+ new_hash = hash.clone
111
+ new_hash[key] = []
112
+ YAML.stub(:load_file){|filename| new_hash }
113
+ c = Configuration.new
114
+ c.parse_yaml("config.yml")
115
+ STDERR.should_receive(:puts).with(/Configuration file is invalid! Pls. define at least one .* in #{key} section/)
116
+ lambda{c.validate}.should raise_error(SystemExit)
117
+ end
118
+ end
119
+ end
120
+ end
121
+
122
+ context "#creep_modifier_class" do
123
+ it "should return creep_modifier_class from config if type specified" do
124
+ config_parsed.creep_modifier_class('b').should eql(String)
125
+ end
126
+ it "should return creep_modifier_class from config for default type if not type specified" do
127
+ config_parsed.creep_modifier_class.should eql(Object)
128
+ end
129
+ end
130
+
131
+ context "#ant_colony_class" do
132
+ it "should return creep_modifier_class from config if type specified" do
133
+ config_parsed.ant_colony_class('b').should eql(Hash)
134
+ end
135
+ it "should return creep_modifier_class from config for default type if not type specified" do
136
+ config_parsed.ant_colony_class.should eql(String)
137
+ end
138
+ end
139
+
140
+ context "#get_class_by_type_and_object" do
141
+ it "should log error if no class name defiend for given type and object" do
142
+ Log.logger_for.should_receive(:error).with(/No class configuration defined for object and type a/)
143
+ Log.logger_for.should_receive(:error).with(/No class configuration defined for String and type d/)
144
+ config_parsed.get_class_by_type_and_object('a', 'object')
145
+ config_parsed.get_class_by_type_and_object('d', 'String')
146
+ end
147
+ it "should log error if no specified class defiend" do
148
+ Log.logger_for.should_receive(:error).with("No such class defined: SomeClass")
149
+ config_parsed.get_class_by_type_and_object('c', 'ant_colony_class')
150
+ end
151
+ end
152
+
153
+ context "#[]" do
154
+ it "should access to configuration with [] method" do
155
+ config_parsed['default_type'].should eql('a')
156
+ config_parsed['default_type'].should eql('a')
157
+ end
158
+ end
159
+
160
+ context "#method_missing" do
161
+ it "should return default_type from config" do
162
+ config_parsed.default_type.should eql("a")
163
+ end
164
+ end
165
+
166
+ context "Configuration#config" do
167
+ let(:config_double){
168
+ config_double = double("config")
169
+ config_double.stub(:parse_yaml){|file| }
170
+ config_double.stub(:validate)
171
+ config_double.stub(:require_libs)
172
+ config_double
173
+ }
174
+ before :each do
175
+ Configuration.method(:remove_class_variable).call(:@@config) if Configuration.class_variable_defined?(:@@config)
176
+ end
177
+ it "should return same object every time" do
178
+ Configuration.stub(:new){config_double}
179
+ config_double.should_receive(:parse_yaml)
180
+ config_double.should_receive(:validate)
181
+ config_double.should_receive(:require_libs)
182
+ Configuration.config.should be_equal(Configuration.config)
183
+ end
184
+ it "should use passed filename for parsing" do
185
+ Configuration.stub(:new){ config_double }
186
+ config_double.should_receive(:parse_yaml).with("filename.yml")
187
+ config_double.should_receive(:require_libs)
188
+ config_double.should_receive(:validate)
189
+ Configuration.config("filename.yml")
190
+ end
191
+ it "should use ARGV[0] as filename for parsing" do
192
+ Configuration.stub(:new){ config_double }
193
+ ARGV[0]='filename.yml'
194
+ config_double.should_receive(:parse_yaml).with("filename.yml")
195
+ config_double.should_receive(:require_libs)
196
+ config_double.should_receive(:validate)
197
+ Configuration.config
198
+ end
199
+ end
200
+ end
201
+ end