answer-factory 0.0.9 → 0.0.10
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/Rakefile +1 -0
- data/Thorfile +9 -6
- data/VERSION +1 -1
- data/answer-factory.gemspec +20 -5
- data/lib/answer-factory.rb +14 -2
- data/lib/answers/answer.rb +17 -3
- data/lib/answers/batch.rb +15 -3
- data/lib/factories/workstation.rb +50 -1
- data/lib/operators/all_duplicated_genomes_sampler.rb +14 -0
- data/lib/operators/any_one_sampler.rb +7 -0
- data/lib/operators/dominated_quantile_selector.rb +16 -0
- data/lib/operators/infrastructure.rb +74 -0
- data/lib/operators/most_dominated_subset_sampler.rb +13 -0
- data/lib/operators/nondominated_subset_selector.rb +17 -0
- data/lib/operators/point_crossover_operator.rb +24 -0
- data/lib/operators/point_delete_operator.rb +19 -0
- data/lib/operators/point_mutation_operator.rb +22 -0
- data/lib/operators/program_point_count_evaluator.rb +14 -0
- data/lib/operators/random_guess_operator.rb +30 -0
- data/lib/operators/resample_and_clone_operator.rb +28 -0
- data/lib/operators/resample_values_operator.rb +40 -0
- data/lib/operators/{evaluators.rb → test_case_evaluator.rb} +3 -34
- data/lib/operators/uniform_backbone_crossover_operator.rb +53 -0
- data/readme.md +28 -3
- data/spec/answer_spec.rb +33 -1
- data/spec/batch_spec.rb +25 -12
- data/spec/factories/factory_spec.rb +53 -36
- data/spec/factories/workstation_spec.rb +194 -20
- data/spec/operators/evaluators/program_point_evaluator_spec.rb +1 -1
- data/spec/operators/evaluators/test_case_evaluator_spec.rb +2 -2
- data/spec/operators/nondominated_subset_spec.rb +8 -8
- data/spec/operators/random_guess_spec.rb +16 -11
- data/spec/operators/resample_and_clone_spec.rb +8 -8
- data/spec/operators/uniformBackboneCrossover_spec.rb +7 -7
- data/spec/spec_helper.rb +1 -0
- metadata +38 -12
- data/lib/operators/basic_operators.rb +0 -240
- data/lib/operators/samplers_and_selectors.rb +0 -131
@@ -0,0 +1,19 @@
|
|
1
|
+
module AnswerFactory
|
2
|
+
class PointDeleteOperator < SearchOperator
|
3
|
+
def generate(crowd, howManyCopies = 1)
|
4
|
+
raise(ArgumentError) if !crowd.kind_of?(Array)
|
5
|
+
crowd.each {|dude| raise(ArgumentError) if !dude.kind_of?(Answer) }
|
6
|
+
|
7
|
+
result = Batch.new
|
8
|
+
crowd.each do |dude|
|
9
|
+
howManyCopies.times do
|
10
|
+
where = rand(dude.points)+1
|
11
|
+
variant = dude.delete_point_or_clone(where)
|
12
|
+
baby = Answer.new(variant, progress:dude.progress + 1)
|
13
|
+
result << baby
|
14
|
+
end
|
15
|
+
end
|
16
|
+
return result
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module AnswerFactory
|
2
|
+
class PointMutationOperator < SearchOperator
|
3
|
+
|
4
|
+
def generate(crowd, howManyCopies = 1, overridden_options ={})
|
5
|
+
raise(ArgumentError) if !crowd.kind_of?(Array)
|
6
|
+
raise(ArgumentError) if crowd.empty?
|
7
|
+
crowd.each {|dude| raise(ArgumentError) if !dude.kind_of?(Answer) }
|
8
|
+
|
9
|
+
result = Batch.new
|
10
|
+
crowd.each do |dude|
|
11
|
+
howManyCopies.times do
|
12
|
+
where = rand(dude.points)+1
|
13
|
+
newCode = CodeType.any_value(@incoming_options.merge(overridden_options))
|
14
|
+
variant = dude.replace_point_or_clone(where,newCode)
|
15
|
+
baby = Answer.new(variant, progress:dude.progress + 1)
|
16
|
+
result << baby
|
17
|
+
end
|
18
|
+
end
|
19
|
+
return result
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module AnswerFactory
|
2
|
+
class ProgramPointEvaluator < Evaluator
|
3
|
+
def evaluate(batch)
|
4
|
+
raise(ArgumentError, "Can only evaluate a Batch of Answers") if !batch.kind_of?(Batch)
|
5
|
+
batch.each do |i|
|
6
|
+
if i.parses?
|
7
|
+
i.scores[@score_label] = i.program.points
|
8
|
+
else
|
9
|
+
raise(ArgumentError, "Program is not parseable")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module AnswerFactory
|
2
|
+
class RandomGuessOperator < SearchOperator
|
3
|
+
|
4
|
+
# returns an Array of random Answers
|
5
|
+
#
|
6
|
+
# the first (optional) parameter specifies how many to make, and defaults to 1
|
7
|
+
# the second (also optional) parameter is a hash that
|
8
|
+
# can temporarily override those set in the initialization
|
9
|
+
#
|
10
|
+
# For example, if
|
11
|
+
# <tt>myRandomGuesser = RandomGuessOperator.new(:randomIntegerLowerBound => -90000)</tt>
|
12
|
+
#
|
13
|
+
# [<tt>myRandomGuesser.generate()</tt>]
|
14
|
+
# produces a list of 1 Answer, and if it has any IntType samples they will be in [-90000,100]
|
15
|
+
# (since the default +:randomIntegerLowerBound+ is 100)
|
16
|
+
# [<tt>myRandomGuesser.generate(1,:randomIntegerLowerBound => 0)</tt>]
|
17
|
+
# makes one Answer whose IntType samples (if any) will be between [0,100]
|
18
|
+
|
19
|
+
def generate(crowd, overridden_options = {})
|
20
|
+
every_option = @incoming_options.merge(overridden_options)
|
21
|
+
how_many = every_option[:how_many] || 1
|
22
|
+
how_many.times do
|
23
|
+
newGenome = CodeType.any_value(every_option)
|
24
|
+
newDude = Answer.new(newGenome, progress:0)
|
25
|
+
crowd << newDude
|
26
|
+
end
|
27
|
+
return crowd
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module AnswerFactory
|
2
|
+
class ResampleAndCloneOperator < SearchOperator
|
3
|
+
|
4
|
+
# returns an Array of clones of Answers randomly selected from the crowd passed in
|
5
|
+
#
|
6
|
+
# the first (required) parameter is an Array of Answers
|
7
|
+
# the second (optional) parameter is how many samples to take, and defaults to 1
|
8
|
+
#
|
9
|
+
# For example, if
|
10
|
+
# <tt>@currentPopulation = [a list of 300 Answers]</tt> and
|
11
|
+
# <tt>myRandomSampler = ResampleAndCloneOperator.new(@currentPopulation)</tt>
|
12
|
+
# [<tt>myRandomSampler.generate()</tt>]
|
13
|
+
# produces a list of 1 Answer, which is a clone of somebody from <tt>@currentPopulation</tt>
|
14
|
+
# [<tt>myRandomGuesser.generate(11)</tt>]
|
15
|
+
# returns a list of 11 Answers cloned from <tt>@currentPopulation</tt>,
|
16
|
+
# possibly including repeats
|
17
|
+
|
18
|
+
def generate(crowd, howMany = 1)
|
19
|
+
result = Batch.new
|
20
|
+
howMany.times do
|
21
|
+
donor = crowd.sample
|
22
|
+
clone = Answer.new(donor.blueprint, progress:donor.progress + 1)
|
23
|
+
result << clone
|
24
|
+
end
|
25
|
+
return result
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
module AnswerFactory
|
3
|
+
|
4
|
+
class ResampleValuesOperator < SearchOperator
|
5
|
+
|
6
|
+
def generate(crowd, howManyCopies = 1, overridden_options = {})
|
7
|
+
crowd.each {|dude| raise(ArgumentError) if !dude.kind_of?(Answer) }
|
8
|
+
|
9
|
+
result = Batch.new
|
10
|
+
regenerating_options = @incoming_options.merge(overridden_options)
|
11
|
+
crowd.each do |dude|
|
12
|
+
howManyCopies.times do
|
13
|
+
wildtype_program = dude.program
|
14
|
+
starting_footnotes = wildtype_program.footnote_section.split( /^(?=«)/ )
|
15
|
+
breaker = /^«([a-zA-Z][a-zA-Z0-9_]*)»\s*(.*)\s*/m
|
16
|
+
type_value_pairs = starting_footnotes.collect {|fn| fn.match(breaker)[1..2]}
|
17
|
+
|
18
|
+
mutant_blueprint = wildtype_program.code_section
|
19
|
+
|
20
|
+
type_value_pairs.each do |pair|
|
21
|
+
|
22
|
+
begin
|
23
|
+
type_name = pair[0]
|
24
|
+
type_class = "#{type_name}_type".camelize.constantize
|
25
|
+
reduced_size = regenerating_options[:target_size_in_points] || rand(dude.points/2)
|
26
|
+
reduced_option = {target_size_in_points:reduced_size}
|
27
|
+
resampled_value = type_class.any_value(regenerating_options.merge(reduced_option)).to_s
|
28
|
+
rescue NameError
|
29
|
+
resampled_value = pair[1]
|
30
|
+
end
|
31
|
+
mutant_blueprint << "\n«#{pair[0].strip}» #{resampled_value.strip}"
|
32
|
+
end
|
33
|
+
mutant = Answer.new(mutant_blueprint, progress:dude.progress + 1)
|
34
|
+
result << mutant
|
35
|
+
end
|
36
|
+
end
|
37
|
+
return result
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -1,35 +1,4 @@
|
|
1
1
|
module AnswerFactory
|
2
|
-
|
3
|
-
class Evaluator < SearchOperator
|
4
|
-
attr_accessor :name
|
5
|
-
|
6
|
-
def initialize(params = {})
|
7
|
-
raise(ArgumentError, "Evaluators must be initialized with names") if params[:name] == nil
|
8
|
-
@name = params[:name]
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
class ProgramPointEvaluator < Evaluator
|
17
|
-
def evaluate(batch)
|
18
|
-
raise(ArgumentError, "Can only evaluate a Batch of Answers") if !batch.kind_of?(Batch)
|
19
|
-
batch.each do |i|
|
20
|
-
if i.parses?
|
21
|
-
i.scores[@name] = i.program.points
|
22
|
-
else
|
23
|
-
raise(ArgumentError, "Program is not parseable")
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
2
|
class TestCase
|
34
3
|
attr_accessor :bindings, :expectations, :gauges
|
35
4
|
|
@@ -59,7 +28,7 @@ module AnswerFactory
|
|
59
28
|
variable_names = params[:references] || []
|
60
29
|
|
61
30
|
batch.each do |dude|
|
62
|
-
if !params[:deterministic] || !dude.scores[@
|
31
|
+
if !params[:deterministic] || !dude.scores[@score_label]
|
63
32
|
score = 0
|
64
33
|
readings = {}
|
65
34
|
cases.each do |example|
|
@@ -100,11 +69,11 @@ module AnswerFactory
|
|
100
69
|
score += difference.abs
|
101
70
|
end
|
102
71
|
# aggregate differences
|
103
|
-
dude.scores[@
|
72
|
+
dude.scores[@score_label] = score.to_f / cases.length
|
104
73
|
|
105
74
|
puts "#{score.to_f / cases.length}" if params[:feedback]
|
106
75
|
else
|
107
|
-
puts dude.scores[@
|
76
|
+
puts dude.scores[@score_label] if params[:feedback]
|
108
77
|
end
|
109
78
|
end
|
110
79
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module AnswerFactory
|
2
|
+
class UniformBackboneCrossoverOperator < SearchOperator
|
3
|
+
|
4
|
+
# Returns a Batch of new Answers whose programs are made by stitching together
|
5
|
+
# the programs of pairs of 'parents'. The incoming Batch is divided into pairs based on
|
6
|
+
# adjacency (modulo the Batch.length), one pair for each 'offspring' to be made. To make
|
7
|
+
# an offspring, the number of backbone program points is determined in each parent; 'backbone'
|
8
|
+
# refers to the number of branches directly within the root of the program, not the entire tree.
|
9
|
+
#
|
10
|
+
# To construct an offspring's program, program points are copied from the first parent with
|
11
|
+
# probability p, or the second parent with probability (1-p), for each point in the first
|
12
|
+
# parent's backbone. So if there are 13 and 6 points, respectively, the first six points are
|
13
|
+
# selected randomly, but the last 7 are copied from the first parent. If there are 8 and 11
|
14
|
+
# respectively, then the last 3 will be ignored from the second parent in any case.
|
15
|
+
#
|
16
|
+
# the first (required) parameter is an Array of Answers
|
17
|
+
# the second (optional) parameter is how many crossovers to make,
|
18
|
+
# which defaults to the number of Answers in the incoming Batch
|
19
|
+
|
20
|
+
def generate(crowd, howMany = crowd.length, prob = 0.5)
|
21
|
+
result = Batch.new
|
22
|
+
howMany.times do
|
23
|
+
where = rand(crowd.length)
|
24
|
+
mom = crowd[where]
|
25
|
+
dad = crowd[ (where+1) % crowd.length ]
|
26
|
+
mom_backbone_length = mom.program[1].contents.length
|
27
|
+
dad_backbone_length = dad.program[1].contents.length
|
28
|
+
|
29
|
+
baby_blueprint_parts = ["",""]
|
30
|
+
(0..mom_backbone_length-1).each do |backbone_point|
|
31
|
+
if rand() < prob
|
32
|
+
next_chunks = mom.program[1].contents[backbone_point].blueprint_parts || ["",""]
|
33
|
+
else
|
34
|
+
if backbone_point < dad_backbone_length
|
35
|
+
next_chunks = (dad.program[1].contents[backbone_point].blueprint_parts || ["", ""])
|
36
|
+
else
|
37
|
+
next_chunks = ["",""]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
baby_blueprint_parts[0] << " #{next_chunks[0]}"
|
41
|
+
baby_blueprint_parts[1] << " \n#{next_chunks[1]}"
|
42
|
+
end
|
43
|
+
mom.program.unused_footnotes.each {|fn| baby_blueprint_parts[1] += "\n#{fn}"}
|
44
|
+
|
45
|
+
baby_blueprint = "block {#{baby_blueprint_parts[0]}} #{baby_blueprint_parts[1]}"
|
46
|
+
baby = Answer.new(baby_blueprint, progress:[mom.progress,dad.progress].max + 1)
|
47
|
+
|
48
|
+
result << baby
|
49
|
+
end
|
50
|
+
return result
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/readme.md
CHANGED
@@ -22,10 +22,35 @@ The AnswerFactory infrastructure has been designed to help _regular people_ buil
|
|
22
22
|
|
23
23
|
## Getting started
|
24
24
|
|
25
|
-
|
25
|
+
The `answer-factory` gem depends on Ruby 1.9 or higher. We recommend [rvm](http://rvm.beginrescueend.com/) if you'd like to maintain several Ruby installations.
|
26
26
|
|
27
|
-
|
27
|
+
You'll also need a working installation of [CouchDB](http://couchdb.apache.org/) available. This can be a remote instance, as long as you have the necessary permissions to create and manage databases.
|
28
28
|
|
29
|
+
Then:
|
29
30
|
gem install answer-factory
|
30
31
|
|
31
|
-
This
|
32
|
+
This will automatically install several dependencies, including [nudge](http://github.com/Vaguery/Nudge), rspec, and others.
|
33
|
+
|
34
|
+
### Creating a new AnswerFactory project
|
35
|
+
|
36
|
+
Use this command line script to build an AnswerFactory project folder:
|
37
|
+
answer-factory your-project-name-here
|
38
|
+
|
39
|
+
This will create a new directory called 'your-project-name-here', and install a rudimentary subtree of folders and files. Perhaps most important is the `Thorfile`, which contains most of the generators you can use to simplify project creation and management.
|
40
|
+
|
41
|
+
### Replicating a pre-existing project or demo
|
42
|
+
|
43
|
+
TBD
|
44
|
+
|
45
|
+
### Generating new Nudge type defintitions
|
46
|
+
|
47
|
+
The Nudge language gem installed along with `answer-factory` includes a full-featured programming language designed for genetic programming projects, with integer, floating-point, boolean, and code types.
|
48
|
+
|
49
|
+
Often your project's domain model will call for additional types. To generate some basic infrastructure for a new NudgeType subclass, navigate to the root of your project folder and invoke the thor script
|
50
|
+
thor new_nudge_type your-nudge-type-name
|
51
|
+
This will create a template for your class definition in the `/lib/nudge/types` subdirectory (which you should edit as indicated in the comments to use), several standard nudge instruction classes in `/lib/nudge/instructions`, and rspec files.
|
52
|
+
|
53
|
+
### Activating the AnswerFactory daemon
|
54
|
+
|
55
|
+
Make sure CouchDB is running and available, navigate to your project's root folder, and invoke
|
56
|
+
ruby activate.rb
|
data/spec/answer_spec.rb
CHANGED
@@ -78,7 +78,7 @@ describe "Answer" do
|
|
78
78
|
describe "serialization" do
|
79
79
|
describe "writing" do
|
80
80
|
before(:each) do
|
81
|
-
@a1 = Answer.new("block {do a}")
|
81
|
+
@a1 = Answer.new("block {do a}", progress:12)
|
82
82
|
end
|
83
83
|
|
84
84
|
it "should contain the blueprint" do
|
@@ -94,12 +94,44 @@ describe "Answer" do
|
|
94
94
|
@a1.data['scores'].should == @a1.scores
|
95
95
|
end
|
96
96
|
|
97
|
+
it "should contain the progress" do
|
98
|
+
@a1.data['progress'].should == @a1.progress
|
99
|
+
end
|
100
|
+
|
101
|
+
|
97
102
|
it "should contain the timestamp" do
|
98
103
|
@a1.data['timestamp'].should == @a1.timestamp
|
99
104
|
end
|
100
105
|
end
|
101
106
|
|
102
107
|
describe "reading" do
|
108
|
+
before(:each) do
|
109
|
+
@couchified = {"id"=>"0f60c293ad736abfdb083d33f71ef9ab", "key"=>"ws1", "value"=>{"_id"=>"0f60c293ad736abfdb083d33f71ef9ab", "_rev"=>"1-473467b6dc1a4cba3498dd6eeb8e3206", "blueprint"=>"do bar", "tags"=>["quux", "whatevz"], "scores"=>{"badness" => 12.345}, "progress" => 12, "timestamp"=>"2010/04/14 17:09:14 +0000"}}
|
110
|
+
@my_a = Answer.from_serial_hash(@couchified)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should record the couch_doc_id" do
|
114
|
+
@my_a.couch_id.should == "0f60c293ad736abfdb083d33f71ef9ab"
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should accept a blueprint string" do
|
118
|
+
@my_a.blueprint.should == "do bar"
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should collect the tag Array into a Set of symbols" do
|
122
|
+
@my_a.tags.should be_a_kind_of(Set)
|
123
|
+
@my_a.tags.should include(:quux)
|
124
|
+
@my_a.tags.should include(:whatevz)
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should gather up the scores Hash" do
|
128
|
+
@my_a.scores.should be_a_kind_of(Hash)
|
129
|
+
@my_a.scores.should include(:badness)
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should read the progress" do
|
133
|
+
@my_a.progress.should == 12
|
134
|
+
end
|
103
135
|
|
104
136
|
end
|
105
137
|
end
|
data/spec/batch_spec.rb
CHANGED
@@ -74,25 +74,38 @@ describe "Batches" do
|
|
74
74
|
|
75
75
|
describe "reading" do
|
76
76
|
before(:each) do
|
77
|
-
@uri = "http://127.0.0.1
|
77
|
+
@uri = "http://127.0.0.1:5984/my_factory"
|
78
|
+
@design_doc = "ws1/current" # we'll assume this has been set up!
|
79
|
+
@view_uri = "http://127.0.0.1:5984/my_factory/_design/ws1/_view/current"
|
80
|
+
FakeWeb.allow_net_connect = false
|
81
|
+
@canned = '{"total_rows":1,"offset":0,"rows":[{"id":"0f60c293ad736abfdb083d33f71ef9ab","key":"ws1","value":{"_id":"0f60c293ad736abfdb083d33f71ef9ab","_rev":"1-473467b6dc1a4cba3498dd6eeb8e3206","blueprint":"do bar","tags":[],"scores":{},"progress":12,"timestamp":"2010/04/14 17:09:14 +0000"}}]}'
|
82
|
+
|
78
83
|
end
|
79
84
|
|
80
|
-
it "
|
81
|
-
|
85
|
+
it "should connect to the right view in the right design doc in the persistent store" do
|
86
|
+
FakeWeb.register_uri(:any, @view_uri, :body => @canned, :status => [200, "OK"])
|
87
|
+
lambda{Batch.load_from_couch(@uri,@design_doc)}.should_not raise_error
|
88
|
+
# because it hit the right URI!
|
82
89
|
end
|
83
90
|
|
84
|
-
it "should
|
85
|
-
|
86
|
-
|
87
|
-
end
|
91
|
+
it "should handle errors returned from CouchDB"
|
92
|
+
|
93
|
+
it "should handle db connection problems"
|
88
94
|
|
89
|
-
it "should
|
95
|
+
it "should create an Answer for every row received" do
|
96
|
+
FakeWeb.register_uri(:any, @view_uri, :body => @canned, :status => [200, "OK"])
|
97
|
+
little_batch = Batch.load_from_couch(@uri,@design_doc)
|
98
|
+
little_batch.length.should == 1
|
99
|
+
little_batch[0].blueprint.should == "do bar"
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should raise an warning and create an empty Batch if it can't parse the result" do
|
103
|
+
FakeWeb.register_uri(:any, @view_uri, :body => "some random crap", :status => [200, "OK"])
|
104
|
+
little_batch = Batch.load_from_couch(@uri,@design_doc)
|
105
|
+
little_batch.length.should == 0
|
106
|
+
end
|
90
107
|
end
|
91
108
|
|
92
109
|
end
|
93
|
-
|
94
|
-
|
95
|
-
it "should have a Batch.load_from_couch method that reads a bunch of Answers from the db"
|
96
|
-
|
97
110
|
end
|
98
111
|
end
|
@@ -11,6 +11,59 @@ describe "Factory" do
|
|
11
11
|
Factory.new.name.should == "my_factory"
|
12
12
|
end
|
13
13
|
|
14
|
+
|
15
|
+
describe "databases" do
|
16
|
+
describe "#couch_available?" do
|
17
|
+
it "should have a method to check that couchDB is accessible" do
|
18
|
+
f1 = Factory.new("boo")
|
19
|
+
lambda{f1.couch_available?}.should_not raise_error
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should return true if the uri is reachable" do
|
23
|
+
uri = "http://mycouch.db/boo"
|
24
|
+
f1 = Factory.new("boo")
|
25
|
+
f1.configatron.couchdb_uri = uri
|
26
|
+
FakeWeb.register_uri(:any, uri, :body => "We are here!", :status => [200, "OK"])
|
27
|
+
f1.couch_available?.should == true
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should return false if the uri is offline or 404's out" do
|
31
|
+
uri = "http://mycouch.db/boo"
|
32
|
+
f1 = Factory.new("boo")
|
33
|
+
f1.configatron.couchdb_uri = uri
|
34
|
+
f1.configatron.couchdb_uri.should == uri
|
35
|
+
FakeWeb.register_uri(:any, uri, :body => "Go away!", :status => [404, "Not Found"])
|
36
|
+
f1.couch_available?.should == false
|
37
|
+
|
38
|
+
f1 = Factory.new("boo") # depends on this being wrong
|
39
|
+
f1.configatron.couchdb_uri = "http://127.0.0.1:9991/place"
|
40
|
+
f1.couch_available?.should == false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
describe "build" do
|
47
|
+
it "should read the config files"
|
48
|
+
|
49
|
+
it "should #reset"
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
describe "reset" do
|
54
|
+
it "should erase the couchdb"
|
55
|
+
|
56
|
+
it "should set up a new couchdb"
|
57
|
+
|
58
|
+
it "should set up the necessary design documents in the db"
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
describe "activate" do
|
63
|
+
it "should check the config files"
|
64
|
+
end
|
65
|
+
|
66
|
+
|
14
67
|
describe "ontology" do
|
15
68
|
it "should have a master Instruction list" do
|
16
69
|
Factory.new("foo").instruction_library.should == Instruction.all_instructions
|
@@ -44,43 +97,7 @@ describe "Factory" do
|
|
44
97
|
Factory.new.workstation_names.should == []
|
45
98
|
end
|
46
99
|
|
47
|
-
describe "build_workstation" do
|
48
|
-
it "should create a new workstation"
|
49
|
-
it "should set up all the interior dynamics of the workstation"
|
50
|
-
it "should use the master config for defaults of the new workstation"
|
51
|
-
it "should suffice to create a pass-through workstation just to name it"
|
52
|
-
end
|
53
100
|
end
|
54
101
|
|
55
|
-
describe "activate" do
|
56
|
-
it "should have an #activate method"
|
57
|
-
end
|
58
102
|
|
59
|
-
describe "databases" do
|
60
|
-
|
61
|
-
describe "#couch_available?" do
|
62
|
-
it "should have a method to check that couchDB is accessible" do
|
63
|
-
f1 = Factory.new("boo")
|
64
|
-
lambda{f1.couch_available?}.should_not raise_error
|
65
|
-
end
|
66
|
-
|
67
|
-
it "should return true if the uri is reachable" do
|
68
|
-
uri = "http://mycouch.db/boo"
|
69
|
-
f1 = Factory.new("boo")
|
70
|
-
f1.configatron.couchdb_uri = uri
|
71
|
-
FakeWeb.register_uri(:any, uri, :body => "We are here!", :status => [200, "OK"])
|
72
|
-
f1.couch_available?.should == true
|
73
|
-
end
|
74
|
-
|
75
|
-
it "should return false if the uri is offline or 404's out" do
|
76
|
-
uri = "http://mycouch.db/boo"
|
77
|
-
f1 = Factory.new("boo", couchdb_uri:uri)
|
78
|
-
FakeWeb.register_uri(:any, uri, :body => "Go away!", :status => [404, "Not Found"])
|
79
|
-
f1.couch_available?.should == false
|
80
|
-
|
81
|
-
f1 = Factory.new("boo", couchdb_uri:"http://127.0.0.1:9991/place") # depends on this being wrong
|
82
|
-
f1.couch_available?.should == false
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
103
|
end
|