solve 4.0.0 → 4.0.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.
@@ -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