solve 0.2.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,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Solutions" do
4
+ it "chooses the best artifact for the demands" do
5
+ graph = Solve::Graph.new
6
+ graph.artifacts("mysql", "2.0.0")
7
+ graph.artifacts("mysql", "1.2.0")
8
+ graph.artifacts("nginx", "1.0.0").depends("mysql", "= 1.2.0")
9
+ graph.demands('nginx')
10
+ graph.demands('mysql')
11
+
12
+ Solve.it(graph).should eql("nginx" => "1.0.0", "mysql" => "1.2.0")
13
+ end
14
+
15
+ it "raises NoSolutionError when a solution cannot be found" do
16
+ graph = Solve::Graph.new
17
+ graph.artifacts("mysql", "1.2.0")
18
+
19
+ graph.demands("mysql", ">= 2.0.0")
20
+
21
+ lambda {
22
+ Solve.it!(graph)
23
+ }.should raise_error(Solve::NoSolutionError)
24
+ end
25
+ end
@@ -0,0 +1,22 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ require 'spork'
4
+
5
+ Spork.prefork do
6
+ require 'rspec'
7
+
8
+ APP_ROOT = File.expand_path('../../', __FILE__)
9
+
10
+ Dir[File.join(APP_ROOT, "spec/support/**/*.rb")].each {|f| require f}
11
+
12
+ RSpec.configure do |config|
13
+ config.mock_with :rspec
14
+ config.treat_symbols_as_metadata_keys_with_true_values = true
15
+ config.filter_run focus: true
16
+ config.run_all_when_everything_filtered = true
17
+ end
18
+ end
19
+
20
+ Spork.each_run do
21
+ require 'solve'
22
+ end
@@ -0,0 +1,128 @@
1
+ require 'spec_helper'
2
+
3
+ describe Solve::Artifact do
4
+ let(:graph) do
5
+ package = double('package')
6
+ package_version = double('package_version')
7
+ package_version.stub(:dependencies).and_return([])
8
+ package.stub(:add_version).and_return(package_version)
9
+ double('graph', dep_graph: double('dep_graph', package: package))
10
+ end
11
+
12
+ let(:name) { "league" }
13
+ let(:version) { "1.0.0" }
14
+ subject { Solve::Artifact.new(graph, name, version) }
15
+
16
+ describe "#dependencies" do
17
+ context "given a name and constraint argument" do
18
+ let(:name) { "nginx" }
19
+ let(:constraint) { "~> 0.101.5" }
20
+
21
+ context "given the dependency of the given name and constraint does not exist" do
22
+ it "returns a Solve::Artifact" do
23
+ subject.dependencies(name, constraint).should be_a(Solve::Dependency)
24
+ end
25
+
26
+ it "the dependency has the given name" do
27
+ subject.dependencies(name, constraint).name.should eql(name)
28
+ end
29
+
30
+ it "the dependency has the given constraint" do
31
+ subject.dependencies(name, constraint).constraint.to_s.should eql(constraint)
32
+ end
33
+
34
+ it "adds an dependency to the dependency collection" do
35
+ subject.dependencies(name, constraint)
36
+
37
+ subject.dependencies.should have(1).item
38
+ end
39
+
40
+ it "the dependency added matches the given name" do
41
+ subject.dependencies(name, constraint)
42
+
43
+ subject.dependencies[0].name.should eql(name)
44
+ end
45
+
46
+ it "the dependency added matches the given constraint" do
47
+ subject.dependencies(name, constraint)
48
+
49
+ subject.dependencies[0].constraint.to_s.should eql(constraint)
50
+ end
51
+ end
52
+ end
53
+
54
+ context "given no arguments" do
55
+ it "returns an array" do
56
+ subject.dependencies.should be_a(Array)
57
+ end
58
+
59
+ it "returns an empty array if no dependencies have been accessed" do
60
+ subject.dependencies.should have(0).items
61
+ end
62
+
63
+ it "returns an array containing an dependency if one was accessed" do
64
+ subject.dependencies("nginx", "~> 0.101.5")
65
+
66
+ subject.dependencies.should have(1).item
67
+ end
68
+ end
69
+
70
+ context "given only a name argument" do
71
+ it "returns an array containing a match all constraint (>= 0.0.0)" do
72
+ subject.dependencies("nginx").constraint.to_s.should eql(">= 0.0.0")
73
+ end
74
+ end
75
+
76
+ context "given an unexpected number of arguments" do
77
+ it "raises an ArgumentError if more than two are provided" do
78
+ lambda {
79
+ subject.dependencies(1, 2, 3)
80
+ }.should raise_error(ArgumentError, "Unexpected number of arguments. You gave: 3. Expected: 2 or less.")
81
+ end
82
+
83
+ it "raises an ArgumentError if a name argument is provided but it is nil" do
84
+ lambda {
85
+ subject.dependencies(nil)
86
+ }.should raise_error(ArgumentError, "A name must be specified. You gave: [nil].")
87
+ end
88
+
89
+ it "raises an ArgumentError if a name and constraint argument are provided but the name is nil" do
90
+ lambda {
91
+ subject.dependencies(nil, "= 1.0.0")
92
+ }.should raise_error(ArgumentError, 'A name must be specified. You gave: [nil, "= 1.0.0"].')
93
+ end
94
+ end
95
+ end
96
+
97
+ describe "#delete" do
98
+ context "given the artifact is a member of a graph" do
99
+ subject { Solve::Artifact.new(graph, name, version) }
100
+
101
+ before(:each) do
102
+ graph.should_receive(:remove_artifact).with(subject).and_return(subject)
103
+ end
104
+
105
+ it "notifies the graph that the artifact should be removed" do
106
+ subject.delete
107
+ end
108
+
109
+ it "sets the graph attribute to nil" do
110
+ subject.delete
111
+
112
+ subject.graph.should be_nil
113
+ end
114
+
115
+ it "returns the instance of artifact deleted from the graph" do
116
+ subject.delete.should eql(subject)
117
+ end
118
+ end
119
+
120
+ context "given the artifact is not the member of a graph" do
121
+ subject { Solve::Artifact.new(nil, name, version) }
122
+
123
+ it "returns nil" do
124
+ subject.delete.should be_nil
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,201 @@
1
+ require 'spec_helper'
2
+
3
+ describe Solve::Constraint do
4
+ let(:valid_string) { ">= 0.0.0" }
5
+ let(:invalid_string) { "x23u7089213.*" }
6
+
7
+ describe "ClassMethods" do
8
+ subject { Solve::Constraint }
9
+
10
+ describe "#parse" do
11
+ it "returns an array containing two items" do
12
+ subject.parse(valid_string).should have(2).items
13
+ end
14
+
15
+ it "returns the operator at index 0" do
16
+ subject.parse(valid_string)[0].should eql(">=")
17
+ end
18
+
19
+ it "returns the version string at index 1" do
20
+ subject.parse(valid_string)[1].should eql("0.0.0")
21
+ end
22
+
23
+ context "given a string that does not match the Constraint REGEXP" do
24
+ it "returns nil" do
25
+ subject.parse(invalid_string).should be_nil
26
+ end
27
+ end
28
+
29
+ context "given a string that does not contain an operator" do
30
+ it "returns a constraint constraint with a default operator (=)" do
31
+ subject.parse("1.0.0")[0].should eql("=")
32
+ end
33
+ end
34
+ end
35
+
36
+ describe "#initialize" do
37
+ it "returns a new instance of Constraint" do
38
+ subject.new(valid_string).should be_a(Solve::Constraint)
39
+ end
40
+
41
+ it "assigns the parsed operator to the operator attribute" do
42
+ subject.new(valid_string).operator.should eql(">=")
43
+ end
44
+
45
+ it "assigns the parsed version string as an instance of Version to the version attribute" do
46
+ result = subject.new(valid_string)
47
+
48
+ result.version.should be_a(Solve::Version)
49
+ result.version.to_s.should eql("0.0.0")
50
+ end
51
+
52
+ context "given a string that does not match the Constraint REGEXP" do
53
+ it "raises an InvalidConstraintFormat error" do
54
+ lambda {
55
+ subject.new(invalid_string)
56
+ }.should raise_error(Solve::InvalidConstraintFormat)
57
+ end
58
+ end
59
+
60
+ context "given a nil value" do
61
+ it "raises an InvalidConstraintFormat error" do
62
+ lambda {
63
+ subject.new(nil)
64
+ }.should raise_error(Solve::InvalidConstraintFormat)
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ describe "#satisfies?" do
71
+ subject { Solve::Constraint.new("= 1.0.0") }
72
+
73
+ it "accepts a String for version" do
74
+ subject.satisfies?("1.0.0").should be_true
75
+ end
76
+
77
+ it "accepts a Version for version" do
78
+ subject.satisfies?(Solve::Version.new("1.0.0")).should be_true
79
+ end
80
+
81
+ context "strictly greater than (>)" do
82
+ subject { Solve::Constraint.new("> 1.0.0") }
83
+
84
+ it "returns true if the given version would satisfy the constraint" do
85
+ subject.satisfies?("2.0.0").should be_true
86
+ end
87
+
88
+ it "returns false if the given version would not satisfy the constraint" do
89
+ subject.satisfies?("1.0.0").should be_false
90
+ end
91
+ end
92
+
93
+ context "strictly less than (<)" do
94
+ subject { Solve::Constraint.new("< 1.0.0") }
95
+
96
+ it "returns true if the given version would satisfy the constraint" do
97
+ subject.satisfies?("0.1.0").should be_true
98
+ end
99
+
100
+ it "returns false if the given version would not satisfy the constraint" do
101
+ subject.satisfies?("1.0.0").should be_false
102
+ end
103
+ end
104
+
105
+ context "strictly equal to (=)" do
106
+ subject { Solve::Constraint.new("= 1.0.0") }
107
+
108
+ it "returns true if the given version would satisfy the constraint" do
109
+ subject.satisfies?("1.0.0").should be_true
110
+ end
111
+
112
+ it "returns false if the given version would not satisfy the constraint" do
113
+ subject.satisfies?("1.0.1").should be_false
114
+ end
115
+ end
116
+
117
+ context "greater than or equal to (>=)" do
118
+ subject { Solve::Constraint.new(">= 1.0.0") }
119
+
120
+ it "returns true if the given version is greater than the version constraint" do
121
+ subject.satisfies?("2.0.0").should be_true
122
+ end
123
+
124
+ it "returns true if the given version is equal to the version constraint" do
125
+ subject.satisfies?("1.0.0").should be_true
126
+ end
127
+
128
+ it "returns false if the given version is less than the version constraint" do
129
+ subject.satisfies?("0.9.0").should be_false
130
+ end
131
+ end
132
+
133
+ context "greater than or equal to (<=)" do
134
+ subject { Solve::Constraint.new("<= 1.0.0") }
135
+
136
+ it "returns true if the given version is less than the version constraint" do
137
+ subject.satisfies?("0.9.0").should be_true
138
+ end
139
+
140
+ it "returns true if the given version is equal to the version constraint" do
141
+ subject.satisfies?("1.0.0").should be_true
142
+ end
143
+
144
+ it "returns false if the given version is less than the version constraint" do
145
+ subject.satisfies?("1.0.1").should be_false
146
+ end
147
+ end
148
+
149
+ context "greater than or equal to (~>)" do
150
+ subject { Solve::Constraint.new("~> 1.0.0") }
151
+
152
+ it "returns true if the given version is equal to the version constraint" do
153
+ subject.satisfies?("1.0.0").should be_true
154
+ end
155
+
156
+ context "when the last value in the constraint is for patch" do
157
+ subject { Solve::Constraint.new("~> 1.0.1") }
158
+
159
+ it "returns true if the patch level is greater than the constraint's" do
160
+ subject.satisfies?("1.0.2").should be_true
161
+ end
162
+
163
+ it "returns true if the patch level is equal to the constraint's" do
164
+ subject.satisfies?("1.0.1").should be_true
165
+ end
166
+
167
+ it "returns false if the patch level is less than the constraint's" do
168
+ subject.satisfies?("1.0.0").should be_false
169
+ end
170
+
171
+ it "returns false if the given version is less than the constraint's" do
172
+ subject.satisfies?("0.9.0").should be_false
173
+ end
174
+ end
175
+
176
+ context "when the last value in the constraint is for minor" do
177
+ subject { Solve::Constraint.new("~> 1.1") }
178
+
179
+ it "returns true if the minor level is greater than the constraint's" do
180
+ subject.satisfies?("1.2").should be_true
181
+ end
182
+
183
+ it "returns true if the minor level is equal to the constraint's" do
184
+ subject.satisfies?("1.1").should be_true
185
+ end
186
+
187
+ it "returns true if a patch level is set but the minor level is equal to or greater than the constraint's" do
188
+ subject.satisfies?("1.2.8").should be_true
189
+ end
190
+
191
+ it "returns false if the patch level is less than the constraint's" do
192
+ subject.satisfies?("1.0.1").should be_false
193
+ end
194
+
195
+ it "returns false if the major level is greater than the constraint's" do
196
+ subject.satisfies?("2.0.0").should be_false
197
+ end
198
+ end
199
+ end
200
+ end
201
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ describe Solve::Demand do
4
+ let(:graph) { double('graph') }
5
+ let(:name) { "league" }
6
+
7
+ describe "ClassMethods" do
8
+ subject { Solve::Demand }
9
+
10
+ describe "::initialize" do
11
+ it "accepts a string for the constraint parameter" do
12
+ subject.new(graph, name, "= 0.0.1").constraint.to_s.should eql("= 0.0.1")
13
+ end
14
+
15
+ it "accepts a Solve::Constraint for the constraint parameter" do
16
+ constraint = Solve::Constraint.new("= 0.0.1")
17
+
18
+ subject.new(graph, name, constraint).constraint.should eql(constraint)
19
+ end
20
+ end
21
+ end
22
+
23
+ let(:constraint) { "~> 1.0.0" }
24
+ subject { Solve::Demand.new(graph, name, constraint) }
25
+
26
+ describe "#delete" do
27
+ context "given the artifact is a member of a graph" do
28
+ subject { Solve::Demand.new(graph, name, constraint) }
29
+
30
+ before(:each) do
31
+ graph.should_receive(:remove_demand).with(subject).and_return(subject)
32
+ end
33
+
34
+ it "notifies the graph that the artifact should be removed" do
35
+ subject.delete
36
+ end
37
+
38
+ it "sets the graph attribute to nil" do
39
+ subject.delete
40
+
41
+ subject.graph.should be_nil
42
+ end
43
+
44
+ it "returns the instance of artifact deleted from the graph" do
45
+ subject.delete.should eql(subject)
46
+ end
47
+ end
48
+
49
+ context "given the artifact is not the member of a graph" do
50
+ subject { Solve::Demand.new(nil, name, constraint) }
51
+
52
+ it "returns nil" do
53
+ subject.delete.should be_nil
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ describe Solve::Dependency do
4
+ let(:artifact) { double('artifact') }
5
+ let(:name) { 'nginx' }
6
+ let(:constraint) { "~> 0.0.1" }
7
+
8
+ subject { Solve::Dependency.new(artifact, name, constraint) }
9
+
10
+ describe "#delete" do
11
+ context "given the dependency is a member of an artifact" do
12
+ subject { Solve::Dependency.new(artifact, name, constraint) }
13
+
14
+ before(:each) do
15
+ artifact.should_receive(:remove_dependency).with(subject).and_return(subject)
16
+ end
17
+
18
+ it "notifies the artifact that the dependency should be removed" do
19
+ subject.delete
20
+ end
21
+
22
+ it "sets the artifact attribute to nil" do
23
+ subject.delete
24
+
25
+ subject.artifact.should be_nil
26
+ end
27
+
28
+ it "returns the instance of dependency deleted from the artifact" do
29
+ subject.delete.should eql(subject)
30
+ end
31
+ end
32
+
33
+ context "given the dependency is not the member of an artifact" do
34
+ subject { Solve::Dependency.new(nil, name, constraint) }
35
+
36
+ it "returns nil" do
37
+ subject.delete.should be_nil
38
+ end
39
+ end
40
+ end
41
+
42
+ describe "#eql?" do
43
+ it "returns true if the other object is an instance of Solve::Dependency with the same constraint and artifact" do
44
+ other = Solve::Dependency.new(artifact, name, constraint)
45
+
46
+ subject.should eql(other)
47
+ end
48
+ end
49
+ end