solve 4.0.0 → 4.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,32 +0,0 @@
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.filter_run focus: true
15
- config.run_all_when_everything_filtered = true
16
-
17
- # Run specs in a random order
18
- config.order = :random
19
- end
20
- end
21
-
22
- Spork.each_run do
23
- require "solve"
24
- end
25
-
26
- # Useful for debugging the solver - simply add `ui: TestUI` to a resolver call
27
- class TestUI
28
- def self.say(message = "")
29
- $stdout.print(message + "\n")
30
- $stdout.flush
31
- end
32
- end
@@ -1,137 +0,0 @@
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 "equality" do
17
- context "given an artifact with the same name and version" do
18
- let(:one) { Solve::Artifact.new(graph, "riot", "1.0.0") }
19
- let(:two) { Solve::Artifact.new(graph, "riot", "1.0.0") }
20
-
21
- it "is equal" do
22
- expect(one).to eq(two)
23
- end
24
- end
25
-
26
- context "given an artifact with the same name but different version" do
27
- let(:one) { Solve::Artifact.new(graph, "riot", "1.0.0") }
28
- let(:two) { Solve::Artifact.new(graph, "riot", "2.0.0") }
29
-
30
- it "is not equal" do
31
- expect(one).to_not eq(two)
32
- end
33
- end
34
-
35
- context "given an artifact with the same version but different name" do
36
- let(:one) { Solve::Artifact.new(graph, "riot", "1.0.0") }
37
- let(:two) { Solve::Artifact.new(graph, "league", "1.0.0") }
38
-
39
- it "is not equal" do
40
- expect(one).to_not eq(two)
41
- end
42
- end
43
- end
44
-
45
- describe "sorting" do
46
- let(:one) { Solve::Artifact.new(graph, "riot", "1.0.0") }
47
- let(:two) { Solve::Artifact.new(graph, "riot", "2.0.0") }
48
- let(:three) { Solve::Artifact.new(graph, "riot", "3.0.0") }
49
-
50
- let(:artifacts) do
51
- [
52
- one,
53
- two,
54
- three,
55
- ].shuffle
56
- end
57
-
58
- it "orders artifacts by their version number" do
59
- sorted = artifacts.sort
60
-
61
- expect(sorted[0]).to eq(one)
62
- expect(sorted[1]).to eq(two)
63
- expect(sorted[2]).to eq(three)
64
- end
65
- end
66
-
67
- describe "#dependency?" do
68
- before { subject.depends("nginx", "1.0.0") }
69
-
70
- it "returns false when the dependency does not exist" do
71
- expect(subject).to have_dependency("nginx", "1.0.0")
72
- end
73
-
74
- it "returns true when the dependendency exists" do
75
- expect(subject).to_not have_dependency("apache2", "2.0.0")
76
- end
77
- end
78
-
79
- describe "#dependency" do
80
- before { subject.depends("nginx", "~> 1.2.3") }
81
-
82
- it "returns an instance of Solve::Dependency matching the given name and constraint" do
83
- dependency = subject.dependency("nginx", "~> 1.2.3")
84
-
85
- expect(dependency).to be_a(Solve::Dependency)
86
- expect(dependency.name).to eq("nginx")
87
- expect(dependency.constraint.to_s).to eq("~> 1.2.3")
88
- end
89
- end
90
-
91
- describe "#dependencies" do
92
- it "returns an array" do
93
- expect(subject.dependencies).to be_a(Array)
94
- end
95
-
96
- it "returns an empty array if no dependencies have been accessed" do
97
- expect(subject.dependencies).to be_empty
98
- end
99
-
100
- it "returns all dependencies" do
101
- subject.depends("nginx", "1.0.0")
102
- subject.depends("nginx", "~> 2.0.0")
103
-
104
- expect(subject.dependencies.size).to eq(2)
105
- end
106
- end
107
-
108
- describe "#depends" do
109
- context "given a name and constraint argument" do
110
- let(:name) { "nginx" }
111
- let(:constraint) { "~> 1.0.0" }
112
-
113
- context "given the dependency of the given name and constraint does not exist" do
114
- it "returns a Solve::Artifact" do
115
- expect(subject.depends(name, constraint)).to be_a(Solve::Artifact)
116
- end
117
-
118
- it "adds a dependency with the given name and constraint to the list of dependencies" do
119
- subject.depends(name, constraint)
120
-
121
- expect(subject.dependencies.size).to eq(1)
122
- expect(subject.dependencies.first.name).to eq(name)
123
- expect(subject.dependencies.first.constraint.to_s).to eq(constraint)
124
- end
125
- end
126
- end
127
-
128
- context "given only a name argument" do
129
- it "adds a dependency with a all constraint (>= 0.0.0)" do
130
- subject.depends("nginx")
131
-
132
- expect(subject.dependencies.size).to eq(1)
133
- expect(subject.dependencies.first.constraint.to_s).to eq(">= 0.0.0")
134
- end
135
- end
136
- end
137
- end
@@ -1,53 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe Solve::Demand do
4
- let(:solver) { double("solver") }
5
- let(:name) { "league" }
6
-
7
- describe "#initialize" do
8
- it "accepts a string for the constraint parameter" do
9
- demand = Solve::Demand.new(solver, name, "= 0.0.1")
10
- expect(demand.constraint.to_s).to eq("= 0.0.1")
11
- end
12
-
13
- it "accepts a Semverse::Constraint for the constraint parameter" do
14
- constraint = Semverse::Constraint.new("= 0.0.1")
15
- demand = Solve::Demand.new(solver, name, constraint)
16
-
17
- expect(demand.constraint).to eq(constraint)
18
- end
19
-
20
- context "when no value for 'constraint' is given" do
21
- it "uses a default of >= 0.0.0" do
22
- demand = Solve::Demand.new(solver, name)
23
-
24
- expect(demand.constraint.operator).to eq(">=")
25
- expect(demand.constraint.version.to_s).to eq("0.0.0")
26
- end
27
- end
28
- end
29
-
30
- let(:constraint) { "~> 1.0.0" }
31
- subject { Solve::Demand.new(solver, name, constraint) }
32
-
33
- describe "equality" do
34
- it "returns true when other is a Solve::Demand with the same name and constriant" do
35
- other = Solve::Demand.new(solver, name, constraint)
36
- expect(subject).to eq(other)
37
- end
38
-
39
- it "returns false when other isn't a Solve::Demand" do
40
- expect(subject).to_not eq("chicken")
41
- end
42
-
43
- it "returns false when other is a Solve::Demand with the same name but a different constraint" do
44
- other = Solve::Demand.new(solver, name, "< 3.4.5")
45
- expect(subject).to_not eq(other)
46
- end
47
-
48
- it "returns false when other is a Solve::Demand with the same constraint but a different name" do
49
- other = Solve::Demand.new(solver, "chicken", constraint)
50
- expect(subject).to_not eq(other)
51
- end
52
- end
53
- end
@@ -1,25 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe Solve::Dependency do
4
- describe "#initialize" do
5
- it "uses a default of >= 0.0.0" do
6
- dep = Solve::Dependency.new(double("artifact"), "ntp")
7
-
8
- expect(dep.constraint.operator).to eq(">=")
9
- expect(dep.constraint.version.to_s).to eq("0.0.0")
10
- end
11
- end
12
-
13
- let(:artifact) { double("artifact") }
14
- let(:name) { "nginx" }
15
- let(:constraint) { "~> 0.0.1" }
16
-
17
- subject { Solve::Dependency.new(artifact, name, constraint) }
18
-
19
- describe "#==" do
20
- it "returns true if the other object is an instance of Solve::Dependency with the same constraint and artifact" do
21
- other = Solve::Dependency.new(artifact, name, constraint)
22
- expect(subject).to eq(other)
23
- end
24
- end
25
- end
@@ -1,205 +0,0 @@
1
- require "spec_helper"
2
-
3
- require "solve/gecode_solver"
4
-
5
- describe Solve::GecodeSolver, :gecode do
6
-
7
- before(:all) do
8
- described_class.activate
9
- end
10
-
11
- describe "ClassMethods" do
12
- describe "::timeout" do
13
- subject { described_class.timeout }
14
-
15
- it "returns 30,000 by default" do
16
- expect(subject).to eql(30_000)
17
- end
18
-
19
- context "when the SOLVE_TIMEOUT env variable is set" do
20
- before { ENV.stub(:[]).with("SOLVE_TIMEOUT") { "30" } }
21
-
22
- it "returns the value multiplied by a thousand" do
23
- expect(subject).to eql(30_000)
24
- end
25
- end
26
- end
27
-
28
- describe "::activate" do
29
-
30
- context "when dep_selector is not installed" do
31
-
32
- it "raises EngineNotAvailable" do
33
- exception = LoadError.new("cannot load such file -- dep_selector")
34
- allow(described_class).to receive(:require).with("dep_selector").and_raise(exception)
35
- expect { described_class.activate }.to raise_error(Solve::Errors::EngineNotAvailable)
36
- end
37
-
38
- end
39
-
40
- context "when dep_selector is installed" do
41
-
42
- it "requires dep_selector" do
43
- expect(described_class).to receive(:require).with("dep_selector").and_call_original
44
- described_class.activate
45
- end
46
- end
47
-
48
- end
49
- end
50
-
51
- let(:graph) { double(Solve::Graph) }
52
- let(:demands) { [["mysql"], ["nginx"]] }
53
- subject(:solver) { described_class.new(graph, demands) }
54
-
55
- it "has a list of demands as ruby literals" do
56
- solver.demands_array.should == demands
57
- end
58
-
59
- it "has a list of demands as model objects" do
60
- expected = [
61
- Solve::Demand.new(solver, "mysql"),
62
- Solve::Demand.new(solver, "nginx"),
63
- ]
64
- solver.demands.should == expected
65
- end
66
-
67
- it "has a graph" do
68
- solver.graph.should == graph
69
- end
70
-
71
- describe "when the constraints are solvable" do
72
- let(:graph) do
73
- graph = Solve::Graph.new
74
- graph.artifact("A", "1.0.0")
75
- graph.artifact("B", "1.0.0").depends("A")
76
- graph
77
- end
78
-
79
- let(:demands) { [["A"], ["B"]] }
80
-
81
- it "gives the solution as a Hash" do
82
- solver.resolve.should == { "A" => "1.0.0", "B" => "1.0.0" }
83
- end
84
-
85
- it "gives the solution in sorted form" do
86
- solver.resolve(sorted: true).should == [["A", "1.0.0"], ["B", "1.0.0"]]
87
- end
88
- end
89
-
90
- describe "when the constraints are not solvable" do
91
- let(:error) do
92
- begin
93
- solver.resolve
94
- rescue => e
95
- e
96
- else
97
- raise "Expected resolve to cause an error"
98
- end
99
- end
100
-
101
- context "and dep-selector identifies missing artifacts" do
102
- let(:graph) do
103
- graph = Solve::Graph.new
104
- graph.artifact("A", "1.0.0")
105
- graph
106
- end
107
-
108
- let(:demands) { [ ["Z"] ] }
109
-
110
- it "raises an error detailing the missing artifacts" do
111
- error.to_s.should include("Missing artifacts: Z")
112
- end
113
- end
114
-
115
- context "and dep-selector identifies constraints that exclude all known versions" do
116
- let(:graph) do
117
- graph = Solve::Graph.new
118
- graph.artifact("A", "1.0.0")
119
- graph
120
- end
121
-
122
- let(:demands) { [ ["A", "> 1.0.0"] ] }
123
-
124
- it "raises an error detailing the missing artifacts" do
125
- error.to_s.should include("Required artifacts do not exist at the desired version")
126
- error.to_s.should include("Constraints that match no available version: (A > 1.0.0)")
127
- end
128
- end
129
-
130
- context "and dep-selector identifies dependency conflicts" do
131
- let(:graph) do
132
- graph = Solve::Graph.new
133
- graph.artifact("A", "1.0.0").depends("B").depends("C")
134
- graph.artifact("B", "1.0.0").depends("D", "= 1.0.0")
135
- graph.artifact("C", "1.0.0").depends("D", "= 2.0.0")
136
- graph.artifact("D", "1.0.0")
137
- graph.artifact("D", "2.0.0")
138
- graph
139
- end
140
-
141
- let(:demands) { [ [ "A" ] ] }
142
-
143
- it "raises an error detailing the missing artifacts" do
144
- error.to_s.should include("Demand that cannot be met: (A >= 0.0.0)")
145
- error.to_s.should include("Artifacts for which there are conflicting dependencies: D = 1.0.0 -> []")
146
- end
147
- end
148
-
149
- context "and dep-selector times out looking for a solution" do
150
- let(:selector) { double(DepSelector::Selector) }
151
-
152
- before do
153
- graph.stub(:artifacts).and_return([])
154
- DepSelector::Selector.stub(:new).and_return(selector)
155
- selector.stub(:find_solution).and_raise(DepSelector::Exceptions::TimeBoundExceeded)
156
- end
157
-
158
- it "raises an error explaining no solution could be found" do
159
- error.to_s.should include("The dependency constraints could not be solved in the time allotted.")
160
- end
161
- end
162
-
163
- context "and dep-selector times out looking for dependency conflicts" do
164
- let(:selector) { double(DepSelector::Selector) }
165
-
166
- before do
167
- graph.stub(:artifacts).and_return([])
168
- DepSelector::Selector.stub(:new).and_return(selector)
169
- selector.stub(:find_solution).and_raise(DepSelector::Exceptions::TimeBoundExceededNoSolution)
170
- end
171
-
172
- it "raises a NoSolutionCauseUnknown error to indicate that no debug info was generated" do
173
- error.should be_a_kind_of(Solve::Errors::NoSolutionCauseUnknown)
174
- end
175
-
176
- it "raises an error explaining that no solution exists but the cause could not be determined" do
177
- error.to_s.should include("There is a dependency conflict, but the solver could not determine the precise cause in the time allotted.")
178
- end
179
- end
180
- end
181
-
182
- describe "finding unsatisfiable demands" do
183
- it "partitions demands into satisfiable and not satisfiable"
184
- end
185
-
186
- describe "supporting Serializer interface" do
187
- let(:serializer) { Solve::Solver::Serializer.new }
188
-
189
- before do
190
- graph.stub(:artifacts).and_return([])
191
- end
192
-
193
- it "implements the required interface" do
194
- problem = Solve::Problem.from_solver(solver)
195
- json_string = serializer.serialize(problem)
196
- problem_data = JSON.parse(json_string)
197
- expected_demands = [
198
- { "name" => "mysql", "constraint" => ">= 0.0.0" },
199
- { "name" => "nginx", "constraint" => ">= 0.0.0" },
200
- ]
201
-
202
- problem_data["demands"].should =~ expected_demands
203
- end
204
- end
205
- end