doubleshot 0.2.0-java → 0.3.0-java
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/Doubleshot +16 -6
- data/README-OLD.textile +216 -0
- data/README.textile +38 -182
- data/lib/doubleshot.rb +100 -39
- data/lib/doubleshot/commands/gem.rb +15 -12
- data/lib/doubleshot/commands/test.rb +38 -5
- data/lib/doubleshot/configuration.rb +2 -2
- data/lib/doubleshot/dependencies/dependency.rb +1 -1
- data/lib/doubleshot/dependencies/gem_dependency.rb +2 -10
- data/lib/doubleshot/dependencies/jar_dependency.rb +12 -2
- data/lib/doubleshot/lockfile.rb +9 -6
- data/lib/doubleshot/pom.rb +15 -2
- data/lib/doubleshot/resolver.rb +1 -0
- data/lib/doubleshot/resolver/gem_resolver.rb +45 -0
- data/lib/doubleshot/resolver/gem_resolver/artifact.rb +146 -0
- data/lib/doubleshot/resolver/gem_resolver/demand.rb +57 -0
- data/lib/doubleshot/resolver/gem_resolver/dependency.rb +57 -0
- data/lib/doubleshot/resolver/gem_resolver/errors.rb +37 -0
- data/lib/doubleshot/resolver/gem_resolver/gem_source.rb +58 -0
- data/lib/doubleshot/resolver/gem_resolver/graph.rb +200 -0
- data/lib/doubleshot/resolver/gem_resolver/solver.rb +279 -0
- data/lib/doubleshot/resolver/gem_resolver/solver/constraint_row.rb +29 -0
- data/lib/doubleshot/resolver/gem_resolver/solver/constraint_table.rb +35 -0
- data/lib/doubleshot/resolver/gem_resolver/solver/variable_row.rb +47 -0
- data/lib/doubleshot/resolver/gem_resolver/solver/variable_table.rb +59 -0
- data/lib/doubleshot/resolver/gem_resolver/source.rb +36 -0
- data/lib/doubleshot/resolver/jar_resolver.rb +1 -3
- data/lib/ruby/gem/requirement.rb +9 -0
- data/target/doubleshot.jar +0 -0
- data/test/compiler_spec.rb +31 -3
- data/test/configuration_spec.rb +11 -3
- data/test/dependencies/gem_dependency_spec.rb +3 -17
- data/test/dependencies/jar_dependency_spec.rb +20 -0
- data/test/helper.rb +3 -1
- data/test/helpers/stub_source.rb +120 -0
- data/test/lockfile_spec.rb +9 -17
- data/test/pom_spec.rb +31 -1
- data/test/resolver/gem_resolver/artifact_spec.rb +106 -0
- data/test/resolver/gem_resolver/demand_spec.rb +70 -0
- data/test/resolver/gem_resolver/dependency_spec.rb +33 -0
- data/test/resolver/gem_resolver/gem_source_spec.rb +28 -0
- data/test/resolver/gem_resolver/graph_spec.rb +239 -0
- data/test/resolver/gem_resolver/solver_spec.rb +449 -0
- data/test/resolver/gem_resolver/source_spec.rb +18 -0
- data/test/resolver/gem_resolver_spec.rb +102 -0
- metadata +35 -73
- data/lib/doubleshot/jar.rb +0 -62
@@ -0,0 +1,70 @@
|
|
1
|
+
#!/usr/bin/env jruby
|
2
|
+
|
3
|
+
# encoding: utf-8
|
4
|
+
|
5
|
+
require_relative "../../helper"
|
6
|
+
|
7
|
+
describe Doubleshot::Resolver::GemResolver::Demand do
|
8
|
+
before do
|
9
|
+
@solver = MiniTest::Mock.new
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "ClassMethods" do
|
13
|
+
describe "::new" do
|
14
|
+
it "accepts a string for the constraint parameter" do
|
15
|
+
Doubleshot::Resolver::GemResolver::Demand.new(@solver, "listen", "= 0.0.1")
|
16
|
+
.constraint.to_s.must_equal "= 0.0.1"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "accepts a Gem::Requirement for the constraint parameter" do
|
20
|
+
constraint = Gem::Requirement.new("= 0.0.1")
|
21
|
+
|
22
|
+
Doubleshot::Resolver::GemResolver::Demand.new(@solver, "listen", constraint)
|
23
|
+
.constraint.must_equal constraint
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "when no value for 'constraint' is given" do
|
27
|
+
it "uses a default of >= 0" do
|
28
|
+
Doubleshot::Resolver::GemResolver::Demand.new(@solver, "listen")
|
29
|
+
.constraint.to_s.must_equal ">= 0"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#delete" do
|
36
|
+
describe "given the demand is not the member of a solver" do
|
37
|
+
it "returns nil" do
|
38
|
+
Doubleshot::Resolver::GemResolver::Demand.new(nil, "listen", "~> 1.0.0")
|
39
|
+
.delete.must_be_nil
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "equality" do
|
45
|
+
before do
|
46
|
+
@demand = Doubleshot::Resolver::GemResolver::Demand.new(@solver, "listen", "1.0")
|
47
|
+
end
|
48
|
+
|
49
|
+
it "returns true when other is a Doubleshot::Resolver::GemResolver::Demand with the same name and constriant" do
|
50
|
+
other_demand = Doubleshot::Resolver::GemResolver::Demand.new(@solver, "listen", "1.0")
|
51
|
+
@demand.must_equal other_demand
|
52
|
+
end
|
53
|
+
|
54
|
+
it "returns false when other isn't a Solve::Demand" do
|
55
|
+
@demand.wont_equal "chicken"
|
56
|
+
end
|
57
|
+
|
58
|
+
it "returns false when other is a Solve::Demand with the same name but a different constraint" do
|
59
|
+
other_demand = Doubleshot::Resolver::GemResolver::Demand.new(@solver, "listen", "< 3.4.5")
|
60
|
+
|
61
|
+
@demand.wont_equal other_demand
|
62
|
+
end
|
63
|
+
|
64
|
+
it "returns false when other is a Solve::Demand with the same constraint but a different name" do
|
65
|
+
other_demand = Doubleshot::Resolver::GemResolver::Demand.new(@solver, "chicken", "1.0")
|
66
|
+
|
67
|
+
@demand.wont_equal other_demand
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
#!/usr/bin/env jruby
|
2
|
+
|
3
|
+
# encoding: utf-8
|
4
|
+
|
5
|
+
require_relative "../../helper"
|
6
|
+
|
7
|
+
describe Doubleshot::Resolver::GemResolver::Dependency do
|
8
|
+
before do
|
9
|
+
@dependency = Doubleshot::Resolver::GemResolver::Dependency.new(
|
10
|
+
Doubleshot::Resolver::GemResolver::Artifact.new(nil, "something_using_ntp", "1.0"),
|
11
|
+
"ntp")
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "ClassMethods" do
|
15
|
+
describe "::new" do
|
16
|
+
describe "when no value for 'constraint' is given" do
|
17
|
+
it "uses a default of >= 0" do
|
18
|
+
@dependency.constraint.to_s.must_equal ">= 0"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#eql?" do
|
25
|
+
it "returns true if the other object is an instance of Solve::Dependency with the same constraint and artifact" do
|
26
|
+
other = Doubleshot::Resolver::GemResolver::Dependency.new(
|
27
|
+
Doubleshot::Resolver::GemResolver::Artifact.new(nil, "something_using_ntp", "1.0"),
|
28
|
+
"ntp")
|
29
|
+
|
30
|
+
@dependency.must_equal other
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env jruby
|
2
|
+
|
3
|
+
# encoding: utf-8
|
4
|
+
|
5
|
+
require_relative "../../helper"
|
6
|
+
|
7
|
+
describe Doubleshot::Resolver::GemResolver::Source do
|
8
|
+
|
9
|
+
before do
|
10
|
+
@source = Doubleshot::Resolver::GemResolver::Source.new Doubleshot::Resolver::GemResolver::DEFAULT_REPOSITORY
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "versions" do
|
14
|
+
it "must return a list of available versions for a gem name" do
|
15
|
+
versions = @source.versions("rack")
|
16
|
+
versions.size.must_be :>, 10
|
17
|
+
versions.must_include Gem::Version.new "1.2.0"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "spec" do
|
22
|
+
it "must return a gemspec for a given gem name and version" do
|
23
|
+
gemspec = @source.spec "rack", "1.2.0"
|
24
|
+
gemspec.name.must_equal "rack"
|
25
|
+
gemspec.version.to_s.must_equal "1.2.0"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,239 @@
|
|
1
|
+
#!/usr/bin/env jruby
|
2
|
+
|
3
|
+
# encoding: utf-8
|
4
|
+
|
5
|
+
require_relative "../../helper"
|
6
|
+
|
7
|
+
describe Doubleshot::Resolver::GemResolver::Graph do
|
8
|
+
before do
|
9
|
+
@graph = Doubleshot::Resolver::GemResolver::Graph.new
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "ClassMethods" do
|
13
|
+
describe "::artifact_key" do
|
14
|
+
it "returns a symbol containing the name and version of the artifact" do
|
15
|
+
Doubleshot::Resolver::GemResolver::Graph::artifact_key("nginx", "1.2.3").must_equal :'nginx-1.2.3'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "::dependency_key" do
|
20
|
+
it "returns a symbol containing the name and constraint of the dependency" do
|
21
|
+
Doubleshot::Resolver::GemResolver::Graph::dependency_key("ntp", "= 2.3.4").must_equal :'ntp-= 2.3.4'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#artifacts" do
|
27
|
+
describe "given a name and version argument" do
|
28
|
+
before do
|
29
|
+
@name = "nginx"
|
30
|
+
@version = "0.101.5"
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "given the artifact of the given name and version does not exist" do
|
34
|
+
it "returns a Doubleshot::Resolver::GemResolver::Artifact" do
|
35
|
+
@graph.artifacts(@name, @version).must_be_kind_of Doubleshot::Resolver::GemResolver::Artifact
|
36
|
+
end
|
37
|
+
|
38
|
+
it "the artifact has the given name" do
|
39
|
+
@graph.artifacts(@name, @version).name.must_equal @name
|
40
|
+
end
|
41
|
+
|
42
|
+
it "the artifact has the given version" do
|
43
|
+
@graph.artifacts(@name, @version).version.to_s.must_equal @version
|
44
|
+
end
|
45
|
+
|
46
|
+
it "adds an artifact to the artifacts collection" do
|
47
|
+
@graph.artifacts(@name, @version)
|
48
|
+
|
49
|
+
@graph.artifacts.size.must_equal 1
|
50
|
+
end
|
51
|
+
|
52
|
+
it "the artifact added matches the given name" do
|
53
|
+
@graph.artifacts(@name, @version)
|
54
|
+
|
55
|
+
@graph.artifacts[0].name.must_equal @name
|
56
|
+
end
|
57
|
+
|
58
|
+
it "the artifact added matches the given version" do
|
59
|
+
@graph.artifacts(@name, @version)
|
60
|
+
|
61
|
+
@graph.artifacts[0].version.to_s.must_equal @version
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "given no arguments" do
|
67
|
+
it "returns an array" do
|
68
|
+
@graph.artifacts.must_be_kind_of Array
|
69
|
+
end
|
70
|
+
|
71
|
+
it "returns an empty array if no artifacts have been accessed" do
|
72
|
+
@graph.artifacts.size.must_equal 0
|
73
|
+
end
|
74
|
+
|
75
|
+
it "returns an array containing an artifact if one was accessed" do
|
76
|
+
@graph.artifacts("nginx", "0.101.5")
|
77
|
+
|
78
|
+
@graph.artifacts.size.must_equal 1
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "given an unexpected number of arguments" do
|
83
|
+
it "raises an ArgumentError if more than two are provided" do
|
84
|
+
-> { @graph.artifacts(1, 2, 3) }.must_raise ArgumentError, "Unexpected number of arguments. You gave: 3. Expected: 0 or 2."
|
85
|
+
end
|
86
|
+
|
87
|
+
it "raises an ArgumentError if one argument is provided" do
|
88
|
+
-> { @graph.artifacts(nil) }.must_raise ArgumentError, "Unexpected number of arguments. You gave: 1. Expected: 0 or 2."
|
89
|
+
end
|
90
|
+
|
91
|
+
it "raises an ArgumentError if one of the arguments provided is nil" do
|
92
|
+
-> { @graph.artifacts("nginx", nil) }.must_raise ArgumentError, 'A name and version must be specified. You gave: ["nginx", nil].'
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe "#get_artifact" do
|
98
|
+
before do
|
99
|
+
@graph.artifacts("nginx", "1.0.0")
|
100
|
+
end
|
101
|
+
|
102
|
+
it "returns an instance of artifact of the matching name and version" do
|
103
|
+
artifact = @graph.get_artifact("nginx", "1.0.0")
|
104
|
+
|
105
|
+
artifact.must_be_kind_of Doubleshot::Resolver::GemResolver::Artifact
|
106
|
+
artifact.name.must_equal "nginx"
|
107
|
+
artifact.version.to_s.must_equal "1.0.0"
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "when an artifact of the given name is not in the collection of artifacts" do
|
111
|
+
it "returns nil" do
|
112
|
+
@graph.get_artifact("nothere", "1.0.0").must_be_nil
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe "#versions" do
|
118
|
+
before do
|
119
|
+
@graph.artifacts("nginx", "1.0.0")
|
120
|
+
@graph.artifacts("nginx", "2.0.0")
|
121
|
+
@graph.artifacts("nginx", "3.0.0")
|
122
|
+
@graph.artifacts("nginx", "4.0.0")
|
123
|
+
@graph.artifacts("nginx", "5.0.0")
|
124
|
+
@graph.artifacts("nginx", "4.0.0")
|
125
|
+
end
|
126
|
+
|
127
|
+
it "returns all the artifacts matching the given name" do
|
128
|
+
@graph.versions("nginx").size.must_equal 5
|
129
|
+
end
|
130
|
+
|
131
|
+
describe "given an optional constraint value" do
|
132
|
+
it "returns only the artifacts matching the given constraint value and name" do
|
133
|
+
@graph.versions("nginx", ">= 4.0.0").size.must_equal 2
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe "#add_artifact" do
|
139
|
+
before do
|
140
|
+
@artifact = Doubleshot::Resolver::GemResolver::Artifact.new(@graph, "nginx", "1.0.0")
|
141
|
+
end
|
142
|
+
|
143
|
+
it "adds a Doubleshot::Resolver::GemResolver::Artifact to the collection of artifacts" do
|
144
|
+
@graph.add_artifact @artifact
|
145
|
+
|
146
|
+
@graph.artifacts.must_include @artifact
|
147
|
+
@graph.artifacts.size.must_equal 1
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should not add the same artifact twice to the collection" do
|
151
|
+
@graph.add_artifact @artifact
|
152
|
+
@graph.add_artifact @artifact
|
153
|
+
|
154
|
+
@graph.artifacts.size.must_equal 1
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
describe "#remove_artifact" do
|
159
|
+
before do
|
160
|
+
@artifact = Doubleshot::Resolver::GemResolver::Artifact.new(@graph, "nginx", "1.0.0")
|
161
|
+
end
|
162
|
+
|
163
|
+
describe "given the artifact is a member of the collection" do
|
164
|
+
before do
|
165
|
+
@graph.add_artifact @artifact
|
166
|
+
end
|
167
|
+
|
168
|
+
it "removes the Solve::Artifact from the collection of artifacts" do
|
169
|
+
@graph.remove_artifact(@artifact)
|
170
|
+
|
171
|
+
@graph.artifacts.size.must_equal 0
|
172
|
+
end
|
173
|
+
|
174
|
+
it "returns the removed Solve::Artifact" do
|
175
|
+
@graph.remove_artifact(@artifact).must_equal @artifact
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
describe "given the artifact is not a member of the collection" do
|
180
|
+
it "should return nil" do
|
181
|
+
@graph.remove_artifact(@artifact).must_be_nil
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
describe "#has_artifact?" do
|
187
|
+
before do
|
188
|
+
@artifact = Doubleshot::Resolver::GemResolver::Artifact.new(@graph, "nginx", "1.0.0")
|
189
|
+
end
|
190
|
+
|
191
|
+
it "returns true if the given Solve::Artifact is a member of the collection" do
|
192
|
+
@graph.add_artifact @artifact
|
193
|
+
|
194
|
+
@graph.has_artifact?(@artifact.name, @artifact.version).must_equal true
|
195
|
+
end
|
196
|
+
|
197
|
+
it "returns false if the given Solve::Artifact is not a member of the collection" do
|
198
|
+
@graph.has_artifact?(@artifact.name, @artifact.version).must_equal false
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
describe "eql?" do
|
203
|
+
before do
|
204
|
+
@graph = Doubleshot::Resolver::GemResolver::Graph.new
|
205
|
+
@graph.artifacts("A", "1.0.0").depends("B", "1.0.0")
|
206
|
+
@graph.artifacts("A", "2.0.0").depends("C", "1.0.0")
|
207
|
+
@graph
|
208
|
+
end
|
209
|
+
|
210
|
+
it "returns false if other isn't a Solve::Graph" do
|
211
|
+
@graph.wont_equal "chicken"
|
212
|
+
end
|
213
|
+
|
214
|
+
it "returns true if other is a Solve::Graph with the same artifacts and dependencies" do
|
215
|
+
other = Doubleshot::Resolver::GemResolver::Graph.new
|
216
|
+
other.artifacts("A", "1.0.0").depends("B", "1.0.0")
|
217
|
+
other.artifacts("A", "2.0.0").depends("C", "1.0.0")
|
218
|
+
|
219
|
+
@graph.must_equal other
|
220
|
+
end
|
221
|
+
|
222
|
+
it "returns false if the other is a Solve::Graph with the same artifacts but different dependencies" do
|
223
|
+
other = Doubleshot::Resolver::GemResolver::Graph.new
|
224
|
+
other.artifacts("A", "1.0.0")
|
225
|
+
other.artifacts("A", "2.0.0")
|
226
|
+
|
227
|
+
@graph.wont_equal other
|
228
|
+
end
|
229
|
+
|
230
|
+
it "returns false if the other is a Solve::Graph with the same dependencies but different artifacts" do
|
231
|
+
other = Doubleshot::Resolver::GemResolver::Graph.new
|
232
|
+
other.artifacts("A", "1.0.0").depends("B", "1.0.0")
|
233
|
+
other.artifacts("A", "2.0.0").depends("C", "1.0.0")
|
234
|
+
other.artifacts("B", "1.0.0")
|
235
|
+
|
236
|
+
@graph.wont_equal other
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
@@ -0,0 +1,449 @@
|
|
1
|
+
#!/usr/bin/env jruby
|
2
|
+
|
3
|
+
# encoding: utf-8
|
4
|
+
|
5
|
+
require_relative "../../helper"
|
6
|
+
|
7
|
+
describe Doubleshot::Resolver::GemResolver::Solver do
|
8
|
+
before do
|
9
|
+
@graph = Doubleshot::Resolver::GemResolver::Graph.new
|
10
|
+
@solver = Doubleshot::Resolver::GemResolver::Solver.new(@graph)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "ClassMethods" do
|
14
|
+
describe "::new" do
|
15
|
+
|
16
|
+
it "adds a demand for each element in the array" do
|
17
|
+
solver = Doubleshot::Resolver::GemResolver::Solver.new(@graph, ["nginx", "ntp"])
|
18
|
+
solver.demands.size.must_equal 2
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "when demand_array is an array of array" do
|
22
|
+
it "creates a new demand with the name and constraint of each element in the array" do
|
23
|
+
solver = Doubleshot::Resolver::GemResolver::Solver.new(@graph, [["nginx", "= 1.2.3"], ["ntp", "= 1.0.0"]])
|
24
|
+
|
25
|
+
solver.demands[0].name.must_equal "nginx"
|
26
|
+
solver.demands[0].constraint.to_s.must_equal "= 1.2.3"
|
27
|
+
solver.demands[1].name.must_equal "ntp"
|
28
|
+
solver.demands[1].constraint.to_s.must_equal "= 1.0.0"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "when demand_array is an array of strings" do
|
33
|
+
it "creates a new demand with the name and a default constraint of each element in the array" do
|
34
|
+
solver = Doubleshot::Resolver::GemResolver::Solver.new(@graph, ["nginx", "ntp"])
|
35
|
+
|
36
|
+
solver.demands[0].name.must_equal "nginx"
|
37
|
+
solver.demands[0].constraint.to_s.must_equal ">= 0"
|
38
|
+
solver.demands[1].name.must_equal "ntp"
|
39
|
+
solver.demands[1].constraint.to_s.must_equal ">= 0"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "when demand_array is a mix between an array of arrays and an array of strings" do
|
44
|
+
let(:demand_array) { [["nginx", "= 1.2.3"], "ntp"] }
|
45
|
+
|
46
|
+
it "creates a new demand with the name and default constraint or constraint of each element in the array" do
|
47
|
+
solver = Doubleshot::Resolver::GemResolver::Solver.new(@graph, [["nginx", "= 1.2.3"], "ntp"])
|
48
|
+
|
49
|
+
solver.demands[0].name.must_equal "nginx"
|
50
|
+
solver.demands[0].constraint.to_s.must_equal "= 1.2.3"
|
51
|
+
solver.demands[1].name.must_equal "ntp"
|
52
|
+
solver.demands[1].constraint.to_s.must_equal ">= 0"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "::demand_key" do
|
58
|
+
it "returns a symbol containing the name and constraint of the demand" do
|
59
|
+
demand = Doubleshot::Resolver::GemResolver::Demand.new(MiniTest::Mock.new, "nginx", "= 1.2.3")
|
60
|
+
Doubleshot::Resolver::GemResolver::Solver::demand_key(demand).must_equal :'nginx-= 1.2.3'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "::satisfy_all" do
|
65
|
+
before do
|
66
|
+
@version_1 = Gem::Version.new("3.1.1")
|
67
|
+
@version_2 = Gem::Version.new("3.1.2")
|
68
|
+
|
69
|
+
@constraints = [
|
70
|
+
Gem::Requirement.new("> 3.0.0"),
|
71
|
+
Gem::Requirement.new("<= 3.1.2")
|
72
|
+
]
|
73
|
+
|
74
|
+
@versions = [
|
75
|
+
Gem::Version.new("0.0.1"),
|
76
|
+
Gem::Version.new("0.1.0"),
|
77
|
+
Gem::Version.new("1.0.0"),
|
78
|
+
Gem::Version.new("2.0.0"),
|
79
|
+
Gem::Version.new("3.0.0"),
|
80
|
+
@version_1,
|
81
|
+
@version_2,
|
82
|
+
Gem::Version.new("4.1.0")
|
83
|
+
].shuffle
|
84
|
+
end
|
85
|
+
|
86
|
+
it "returns all of the versions which satisfy all of the given constraints" do
|
87
|
+
solution = Doubleshot::Resolver::GemResolver::Solver::satisfy_all(@constraints, @versions)
|
88
|
+
|
89
|
+
solution.size.must_equal 2
|
90
|
+
solution.must_include @version_1
|
91
|
+
solution.must_include @version_2
|
92
|
+
end
|
93
|
+
|
94
|
+
it "does not return duplicate satisfied versions given multiple duplicate versions" do
|
95
|
+
solution = Doubleshot::Resolver::GemResolver::Solver::satisfy_all(@constraints, [@version_1, @version_1, @version_1])
|
96
|
+
|
97
|
+
solution.size.must_equal 1
|
98
|
+
solution.must_include @version_1
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "::satisfy_best" do
|
103
|
+
before do
|
104
|
+
@versions = [
|
105
|
+
Gem::Version.new("0.0.1"),
|
106
|
+
Gem::Version.new("0.1.0"),
|
107
|
+
Gem::Version.new("1.0.0"),
|
108
|
+
Gem::Version.new("2.0.0"),
|
109
|
+
Gem::Version.new("3.0.0"),
|
110
|
+
Gem::Version.new("3.1.1"),
|
111
|
+
Gem::Version.new("3.1.2"),
|
112
|
+
Gem::Version.new("4.1.0")
|
113
|
+
].shuffle
|
114
|
+
end
|
115
|
+
|
116
|
+
it "returns the best possible match for the given constraints" do
|
117
|
+
Doubleshot::Resolver::GemResolver::Solver::satisfy_best([">= 1.0.0", "< 4.1.0"], @versions)
|
118
|
+
.to_s.must_equal "3.1.2"
|
119
|
+
end
|
120
|
+
|
121
|
+
it "raises a NoSolutionError error given no version matches a constraint" do
|
122
|
+
-> {
|
123
|
+
Doubleshot::Resolver::GemResolver::Solver::satisfy_best(">= 5.0.0", [Gem::Version.new("4.1.0")])
|
124
|
+
}.must_raise Doubleshot::Resolver::GemResolver::Errors::NoSolutionError
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe "#resolve" do
|
130
|
+
before do
|
131
|
+
@graph.artifacts("nginx", "1.0.0")
|
132
|
+
@solver.demands("nginx", "= 1.0.0")
|
133
|
+
end
|
134
|
+
|
135
|
+
it "returns a solution in the form of a Hash" do
|
136
|
+
@solver.resolve.must_be_kind_of Hash
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
describe "#demands" do
|
141
|
+
describe "given a name and constraint argument" do
|
142
|
+
before do
|
143
|
+
@name = "nginx"
|
144
|
+
@constraint = "~> 0.101.5"
|
145
|
+
@demand = @solver.demands(@name, @constraint)
|
146
|
+
end
|
147
|
+
|
148
|
+
describe "given the artifact of the given name and constraint does not exist" do
|
149
|
+
it "returns a Solve::Demand" do
|
150
|
+
@demand.must_be_kind_of Doubleshot::Resolver::GemResolver::Demand
|
151
|
+
end
|
152
|
+
|
153
|
+
it "the artifact has the given name" do
|
154
|
+
@demand.name.must_equal @name
|
155
|
+
end
|
156
|
+
|
157
|
+
it "the artifact has the given constraint" do
|
158
|
+
@demand.constraint.to_s.must_equal @constraint
|
159
|
+
end
|
160
|
+
|
161
|
+
it "adds an artifact to the demands collection" do
|
162
|
+
@solver.demands.size.must_equal 1
|
163
|
+
end
|
164
|
+
|
165
|
+
it "the artifact added matches the given name" do
|
166
|
+
@solver.demands[0].name.must_equal @name
|
167
|
+
end
|
168
|
+
|
169
|
+
it "the artifact added matches the given constraint" do
|
170
|
+
@solver.demands[0].constraint.to_s.must_equal @constraint
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
describe "given only a name argument" do
|
176
|
+
it "returns a demand with a match all version constraint (>= 0)" do
|
177
|
+
@solver.demands("nginx").constraint.to_s.must_equal ">= 0"
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
describe "given no arguments" do
|
182
|
+
it "returns an array" do
|
183
|
+
@solver.demands.must_be_kind_of Array
|
184
|
+
end
|
185
|
+
|
186
|
+
it "returns an empty array if no demands have been accessed" do
|
187
|
+
@solver.demands.size.must_equal 0
|
188
|
+
end
|
189
|
+
|
190
|
+
it "returns an array containing a demand if one was accessed" do
|
191
|
+
@solver.demands("nginx", "~> 0.101.5")
|
192
|
+
@solver.demands.size.must_equal 1
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
describe "given an unexpected number of arguments" do
|
197
|
+
it "raises an ArgumentError if more than two are provided" do
|
198
|
+
-> {
|
199
|
+
@solver.demands(1, 2, 3)
|
200
|
+
}.must_raise ArgumentError, "Unexpected number of arguments. You gave: 3. Expected: 2 or less."
|
201
|
+
end
|
202
|
+
|
203
|
+
it "raises an ArgumentError if a name argument of nil is provided" do
|
204
|
+
-> {
|
205
|
+
@solver.demands(nil)
|
206
|
+
}.must_raise ArgumentError, "A name must be specified. You gave: [nil]."
|
207
|
+
end
|
208
|
+
|
209
|
+
it "raises an ArgumentError if a name and constraint argument are provided but name is nil" do
|
210
|
+
-> {
|
211
|
+
@solver.demands(nil, "= 1.0.0")
|
212
|
+
}.must_raise ArgumentError, 'A name must be specified. You gave: [nil, "= 1.0.0"].'
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
describe "#add_demand" do
|
218
|
+
before do
|
219
|
+
@demand = Doubleshot::Resolver::GemResolver::Demand.new(MiniTest::Mock, "ntp")
|
220
|
+
end
|
221
|
+
|
222
|
+
it "adds a Solve::Artifact to the collection of artifacts" do
|
223
|
+
@solver.add_demand @demand
|
224
|
+
|
225
|
+
@solver.demands.must_include @demand
|
226
|
+
@solver.demands.size.must_equal 1
|
227
|
+
end
|
228
|
+
|
229
|
+
it "should not add the same demand twice to the collection" do
|
230
|
+
@solver.add_demand @demand
|
231
|
+
@solver.add_demand @demand
|
232
|
+
|
233
|
+
@solver.demands.must_include @demand
|
234
|
+
@solver.demands.size.must_equal 1
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
describe "#remove_demand" do
|
239
|
+
before do
|
240
|
+
@demand = Doubleshot::Resolver::GemResolver::Demand.new(MiniTest::Mock, "ntp")
|
241
|
+
end
|
242
|
+
|
243
|
+
describe "given the demand is a member of the collection" do
|
244
|
+
before do
|
245
|
+
@solver.add_demand @demand
|
246
|
+
end
|
247
|
+
|
248
|
+
it "removes the Solve::Artifact from the collection of demands" do
|
249
|
+
@solver.remove_demand @demand
|
250
|
+
@solver.demands.size.must_equal 0
|
251
|
+
end
|
252
|
+
|
253
|
+
it "returns the removed Solve::Artifact" do
|
254
|
+
@solver.remove_demand(@demand).must_equal @demand
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
it "should return nil given the demand is not a member of the collection" do
|
259
|
+
@solver.remove_demand(@demand).must_be_nil
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
describe "#has_demand?" do
|
264
|
+
before do
|
265
|
+
@demand = Doubleshot::Resolver::GemResolver::Demand.new(MiniTest::Mock, "ntp")
|
266
|
+
end
|
267
|
+
|
268
|
+
it "returns true if the given Solve::Artifact is a member of the collection" do
|
269
|
+
@solver.add_demand @demand
|
270
|
+
|
271
|
+
@solver.has_demand?(@demand).must_equal true
|
272
|
+
end
|
273
|
+
|
274
|
+
it "returns false if the given Solve::Artifact is not a member of the collection" do
|
275
|
+
@solver.has_demand?(@demand).must_equal false
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
describe "solutions" do
|
280
|
+
it "chooses the correct artifact for the demands" do
|
281
|
+
@graph.artifacts("mysql", "2.0.0")
|
282
|
+
@graph.artifacts("mysql", "1.2.0")
|
283
|
+
@graph.artifacts("nginx", "1.0.0").depends("mysql", "= 1.2.0")
|
284
|
+
|
285
|
+
result = Doubleshot::Resolver::GemResolver::Solver.new(@graph, [['nginx', '= 1.0.0'], ['mysql']]).resolve
|
286
|
+
|
287
|
+
result.must_equal({"nginx" => "1.0.0", "mysql" => "1.2.0"})
|
288
|
+
end
|
289
|
+
|
290
|
+
it "chooses the best artifact for the demands" do
|
291
|
+
@graph.artifacts("mysql", "2.0.0")
|
292
|
+
@graph.artifacts("mysql", "1.2.0")
|
293
|
+
@graph.artifacts("nginx", "1.0.0").depends("mysql", ">= 1.2.0")
|
294
|
+
|
295
|
+
result = Doubleshot::Resolver::GemResolver::Solver.new(@graph, [['nginx', '= 1.0.0'], ['mysql']]).resolve
|
296
|
+
|
297
|
+
result.must_equal({"nginx" => "1.0.0", "mysql" => "2.0.0"})
|
298
|
+
end
|
299
|
+
|
300
|
+
it "raises NoSolutionError when a solution cannot be found" do
|
301
|
+
@graph.artifacts("mysql", "1.2.0")
|
302
|
+
|
303
|
+
-> {
|
304
|
+
Doubleshot::Resolver::GemResolver::Solver.new(@graph, ['mysql', '>= 2.0.0']).resolve
|
305
|
+
}.must_raise Doubleshot::Resolver::GemResolver::Errors::NoSolutionError
|
306
|
+
end
|
307
|
+
|
308
|
+
it "find the correct solution when backtracking in variables introduced via demands" do
|
309
|
+
@graph.artifacts("D", "1.2.0")
|
310
|
+
@graph.artifacts("D", "1.3.0")
|
311
|
+
@graph.artifacts("D", "1.4.0")
|
312
|
+
@graph.artifacts("D", "2.0.0")
|
313
|
+
@graph.artifacts("D", "2.1.0")
|
314
|
+
|
315
|
+
@graph.artifacts("C", "2.0.0").depends("D", "= 1.2.0")
|
316
|
+
@graph.artifacts("C", "2.1.0").depends("D", ">= 2.1.0")
|
317
|
+
@graph.artifacts("C", "2.2.0").depends("D", "> 2.0.0")
|
318
|
+
|
319
|
+
@graph.artifacts("B", "1.0.0").depends("D", "= 1.0.0")
|
320
|
+
@graph.artifacts("B", "1.1.0").depends("D", "= 1.0.0")
|
321
|
+
@graph.artifacts("B", "2.0.0").depends("D", ">= 1.3.0")
|
322
|
+
@graph.artifacts("B", "2.1.0").depends("D", ">= 2.0.0")
|
323
|
+
|
324
|
+
@graph.artifacts("A", "1.0.0").depends("B", "> 2.0.0")
|
325
|
+
@graph.artifacts("A", "1.0.0").depends("C", "= 2.1.0")
|
326
|
+
@graph.artifacts("A", "1.0.1").depends("B", "> 1.0.0")
|
327
|
+
@graph.artifacts("A", "1.0.1").depends("C", "= 2.1.0")
|
328
|
+
@graph.artifacts("A", "1.0.2").depends("B", "> 1.0.0")
|
329
|
+
@graph.artifacts("A", "1.0.2").depends("C", "= 2.0.0")
|
330
|
+
|
331
|
+
result = Doubleshot::Resolver::GemResolver::Solver.new(@graph, [['A', '~> 1.0.0'], ['D', ">= 2.0.0"]]).resolve
|
332
|
+
|
333
|
+
result.must_equal({"A" => "1.0.1",
|
334
|
+
"B" => "2.1.0",
|
335
|
+
"C" => "2.1.0",
|
336
|
+
"D" => "2.1.0"})
|
337
|
+
end
|
338
|
+
|
339
|
+
it "must correctly resolve when one resolution exists but it is not the latest" do
|
340
|
+
skip "pending: https://github.com/reset/solve/pull/7"
|
341
|
+
|
342
|
+
@graph.artifacts("get-the-old-one", "1.0")
|
343
|
+
.depends("locked-mid-1", ">= 0")
|
344
|
+
.depends("locked-mid-2", ">= 0")
|
345
|
+
@graph.artifacts("get-the-old-one", "0.5")
|
346
|
+
|
347
|
+
@graph.artifacts("locked-mid-1", "2.0").depends("old-bottom", "= 2.0")
|
348
|
+
@graph.artifacts("locked-mid-1", "1.3").depends("old-bottom", "= 0.5")
|
349
|
+
@graph.artifacts("locked-mid-1", "1.0")
|
350
|
+
|
351
|
+
@graph.artifacts("locked-mid-2", "2.0").depends("old-bottom", "= 2.1")
|
352
|
+
@graph.artifacts("locked-mid-2", "1.4").depends("old-bottom", "= 0.5")
|
353
|
+
@graph.artifacts("locked-mid-2", "1.0")
|
354
|
+
|
355
|
+
@graph.artifacts("old-bottom", "2.1")
|
356
|
+
@graph.artifacts("old-bottom", "2.0")
|
357
|
+
@graph.artifacts("old-bottom", "1.0")
|
358
|
+
@graph.artifacts("old-bottom", "0.5")
|
359
|
+
|
360
|
+
Doubleshot::Resolver::GemResolver::Solver.new(@graph, ["get-the-old-one"]).resolve.must_equal(
|
361
|
+
{
|
362
|
+
"get-the-old-one" => "1.0",
|
363
|
+
"locked-mid-1" => "1.3",
|
364
|
+
"locked-mid-2" => "1.4",
|
365
|
+
"old-bottom" => "0.5"
|
366
|
+
})
|
367
|
+
end
|
368
|
+
|
369
|
+
it "finds the correct solution when there is a circular dependency" do
|
370
|
+
@graph.artifacts("A", "1.0.0").depends("B", "1.0.0")
|
371
|
+
@graph.artifacts("B", "1.0.0").depends("C", "1.0.0")
|
372
|
+
@graph.artifacts("C", "1.0.0").depends("A", "1.0.0")
|
373
|
+
|
374
|
+
result = Doubleshot::Resolver::GemResolver::Solver.new(@graph, [["A", "1.0.0"]]).resolve
|
375
|
+
|
376
|
+
result.must_equal({"A" => "1.0.0",
|
377
|
+
"B" => "1.0.0",
|
378
|
+
"C" => "1.0.0"})
|
379
|
+
end
|
380
|
+
|
381
|
+
it "finds the correct solution when there is a p shaped dependency chain" do
|
382
|
+
@graph.artifacts("A", "1.0.0").depends("B", "1.0.0")
|
383
|
+
@graph.artifacts("B", "1.0.0").depends("C", "1.0.0")
|
384
|
+
@graph.artifacts("C", "1.0.0").depends("B", "1.0.0")
|
385
|
+
|
386
|
+
result = Doubleshot::Resolver::GemResolver::Solver.new(@graph, [["A", "1.0.0"]]).resolve
|
387
|
+
|
388
|
+
result.must_equal({"A" => "1.0.0",
|
389
|
+
"B" => "1.0.0",
|
390
|
+
"C" => "1.0.0"})
|
391
|
+
end
|
392
|
+
|
393
|
+
it "finds the correct solution when there is a diamond shaped dependency" do
|
394
|
+
@graph.artifacts("A", "1.0.0")
|
395
|
+
.depends("B", "1.0.0")
|
396
|
+
.depends("C", "1.0.0")
|
397
|
+
@graph.artifacts("B", "1.0.0")
|
398
|
+
.depends("D", "1.0.0")
|
399
|
+
@graph.artifacts("C", "1.0.0")
|
400
|
+
.depends("D", "1.0.0")
|
401
|
+
@graph.artifacts("D", "1.0.0")
|
402
|
+
|
403
|
+
result = Doubleshot::Resolver::GemResolver::Solver.new(@graph, [["A", "1.0.0"]]).resolve
|
404
|
+
|
405
|
+
result.must_equal({"A" => "1.0.0",
|
406
|
+
"B" => "1.0.0",
|
407
|
+
"C" => "1.0.0",
|
408
|
+
"D" => "1.0.0"})
|
409
|
+
end
|
410
|
+
|
411
|
+
it "gives an empty solution when there are no demands" do
|
412
|
+
result = Doubleshot::Resolver::GemResolver::Solver.new(@graph, []).resolve
|
413
|
+
result.must_equal({})
|
414
|
+
end
|
415
|
+
|
416
|
+
it "tries all combinations until it finds a solution" do
|
417
|
+
@graph.artifacts("A", "1.0.0").depends("B", "~> 1.0.0")
|
418
|
+
@graph.artifacts("A", "1.0.1").depends("B", "~> 1.0.0")
|
419
|
+
@graph.artifacts("A", "1.0.2").depends("B", "~> 1.0.0")
|
420
|
+
|
421
|
+
@graph.artifacts("B", "1.0.0").depends("C", "~> 1.0.0")
|
422
|
+
@graph.artifacts("B", "1.0.1").depends("C", "~> 1.0.0")
|
423
|
+
@graph.artifacts("B", "1.0.2").depends("C", "~> 1.0.0")
|
424
|
+
|
425
|
+
@graph.artifacts("C", "1.0.0").depends("D", "1.0.0")
|
426
|
+
@graph.artifacts("C", "1.0.1").depends("D", "1.0.0")
|
427
|
+
@graph.artifacts("C", "1.0.2").depends("D", "1.0.0")
|
428
|
+
|
429
|
+
# ensure we can't find a solution in the above
|
430
|
+
@graph.artifacts("D", "1.0.0").depends("A", "< 0.0.0")
|
431
|
+
|
432
|
+
# Add a solution to the graph that should be reached only after
|
433
|
+
# all of the others have been tried
|
434
|
+
# it must be circular to ensure that no other branch can find it
|
435
|
+
@graph.artifacts("A", "0.0.0").depends("B", "0.0.0")
|
436
|
+
@graph.artifacts("B", "0.0.0").depends("C", "0.0.0")
|
437
|
+
@graph.artifacts("C", "0.0.0").depends("D", "0.0.0")
|
438
|
+
@graph.artifacts("D", "0.0.0").depends("A", "0.0.0")
|
439
|
+
|
440
|
+
result = Doubleshot::Resolver::GemResolver::Solver.new(@graph, [["A"]]).resolve
|
441
|
+
|
442
|
+
result.must_equal({ "A" => "0.0.0",
|
443
|
+
"B" => "0.0.0",
|
444
|
+
"C" => "0.0.0",
|
445
|
+
"D" => "0.0.0"})
|
446
|
+
|
447
|
+
end
|
448
|
+
end
|
449
|
+
end
|