solve 3.1.1 → 4.0.4
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.
- checksums.yaml +5 -5
- data/lib/solve.rb +10 -11
- data/lib/solve/artifact.rb +10 -10
- data/lib/solve/constraint.rb +47 -47
- data/lib/solve/demand.rb +2 -2
- data/lib/solve/dependency.rb +4 -2
- data/lib/solve/errors.rb +3 -3
- data/lib/solve/gecode_solver.rb +98 -95
- data/lib/solve/graph.rb +3 -3
- data/lib/solve/ruby_solver.rb +128 -63
- data/lib/solve/solver/serializer.rb +53 -53
- data/lib/solve/version.rb +1 -1
- metadata +14 -52
- data/.gitignore +0 -20
- data/.travis.yml +0 -22
- data/Gemfile +0 -33
- data/Guardfile +0 -17
- data/NoGecode.gemfile +0 -4
- data/README.md +0 -85
- data/Rakefile +0 -1
- data/Thorfile +0 -36
- data/solve.gemspec +0 -26
- data/spec/acceptance/benchmark.rb +0 -59
- data/spec/acceptance/large_graph_no_solution.rb +0 -18730
- data/spec/acceptance/opscode_ci_graph.rb +0 -18600
- data/spec/acceptance/ruby_solver_solutions_spec.rb +0 -307
- data/spec/acceptance/solutions_spec.rb +0 -317
- data/spec/spec_helper.rb +0 -25
- data/spec/unit/solve/artifact_spec.rb +0 -137
- data/spec/unit/solve/demand_spec.rb +0 -53
- data/spec/unit/solve/dependency_spec.rb +0 -25
- data/spec/unit/solve/gecode_solver_spec.rb +0 -206
- data/spec/unit/solve/graph_spec.rb +0 -130
- data/spec/unit/solve/ruby_solver_spec.rb +0 -166
- data/spec/unit/solve/solver/serializer_spec.rb +0 -33
- data/spec/unit/solve_spec.rb +0 -19
| @@ -1,130 +0,0 @@ | |
| 1 | 
            -
            require "spec_helper"
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            describe Solve::Graph do
         | 
| 4 | 
            -
              describe "#artifact?" do
         | 
| 5 | 
            -
                it "returns true if the given Solve::Artifact is a member of the collection" do
         | 
| 6 | 
            -
                  subject.artifact("nginx", "1.0.0")
         | 
| 7 | 
            -
                  expect(subject).to have_artifact("nginx", "1.0.0")
         | 
| 8 | 
            -
                end
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                it "returns false if the given Solve::Artifact is not a member of the collection" do
         | 
| 11 | 
            -
                  expect(subject).to_not have_artifact("apache", "1.0.0")
         | 
| 12 | 
            -
                  expect(subject).to_not have_artifact("nginx", "11.4.4")
         | 
| 13 | 
            -
                end
         | 
| 14 | 
            -
              end
         | 
| 15 | 
            -
             | 
| 16 | 
            -
              describe "#find" do
         | 
| 17 | 
            -
                before { subject.artifact("nginx", "1.0.0") }
         | 
| 18 | 
            -
             | 
| 19 | 
            -
                it "returns an instance of artifact of the matching name and version" do
         | 
| 20 | 
            -
                  artifact = subject.find("nginx", "1.0.0")
         | 
| 21 | 
            -
             | 
| 22 | 
            -
                  expect(artifact).to be_a(Solve::Artifact)
         | 
| 23 | 
            -
                  expect(artifact.name).to eq("nginx")
         | 
| 24 | 
            -
                  expect(artifact.version.to_s).to eq("1.0.0")
         | 
| 25 | 
            -
                end
         | 
| 26 | 
            -
             | 
| 27 | 
            -
                it "returns nil when the artifact does not exist" do
         | 
| 28 | 
            -
                  expect(subject.find("notthere", "1.0.0")).to be_nil
         | 
| 29 | 
            -
                end
         | 
| 30 | 
            -
              end
         | 
| 31 | 
            -
             | 
| 32 | 
            -
              describe "#artifact" do
         | 
| 33 | 
            -
                let(:name)    { "nginx" }
         | 
| 34 | 
            -
                let(:version) { "1.0.0" }
         | 
| 35 | 
            -
             | 
| 36 | 
            -
                context "given the artifact of the given name and version does not exist" do
         | 
| 37 | 
            -
                  it "returns a Solve::Artifact" do
         | 
| 38 | 
            -
                    expect(subject.artifact(name, version)).to be_a(Solve::Artifact)
         | 
| 39 | 
            -
                  end
         | 
| 40 | 
            -
             | 
| 41 | 
            -
                  it "the artifact has the given name" do
         | 
| 42 | 
            -
                    artifact = subject.artifact(name, version)
         | 
| 43 | 
            -
                    expect(artifact.name).to eq(name)
         | 
| 44 | 
            -
                  end
         | 
| 45 | 
            -
             | 
| 46 | 
            -
                  it "the artifact has the given version" do
         | 
| 47 | 
            -
                    artifact = subject.artifact(name, version)
         | 
| 48 | 
            -
                    expect(artifact.version.to_s).to eq(version)
         | 
| 49 | 
            -
                  end
         | 
| 50 | 
            -
             | 
| 51 | 
            -
                  it "adds an artifact to the artifacts collection" do
         | 
| 52 | 
            -
                    subject.artifact(name, version)
         | 
| 53 | 
            -
                    expect(subject).to have_artifact(name, version)
         | 
| 54 | 
            -
                  end
         | 
| 55 | 
            -
                end
         | 
| 56 | 
            -
              end
         | 
| 57 | 
            -
             | 
| 58 | 
            -
              describe "#artifacts" do
         | 
| 59 | 
            -
                it "returns an array" do
         | 
| 60 | 
            -
                  expect(subject.artifacts).to be_a(Array)
         | 
| 61 | 
            -
                end
         | 
| 62 | 
            -
             | 
| 63 | 
            -
                it "returns an empty array if no artifacts have been accessed" do
         | 
| 64 | 
            -
                  expect(subject.artifacts).to be_empty
         | 
| 65 | 
            -
                end
         | 
| 66 | 
            -
             | 
| 67 | 
            -
                it "returns an array containing an artifact if one was accessed" do
         | 
| 68 | 
            -
                  subject.artifact("nginx", "1.0.0")
         | 
| 69 | 
            -
                  expect(subject.artifacts.size).to eq(1)
         | 
| 70 | 
            -
                end
         | 
| 71 | 
            -
              end
         | 
| 72 | 
            -
             | 
| 73 | 
            -
              describe "#versions" do
         | 
| 74 | 
            -
                before do
         | 
| 75 | 
            -
                  subject.artifact('nginx', '1.0.0')
         | 
| 76 | 
            -
                  subject.artifact('nginx', '2.0.0')
         | 
| 77 | 
            -
                  subject.artifact('nginx', '3.0.0')
         | 
| 78 | 
            -
                  subject.artifact('nginx', '4.0.0')
         | 
| 79 | 
            -
             | 
| 80 | 
            -
                  subject.artifact('other', '1.0.0')
         | 
| 81 | 
            -
                end
         | 
| 82 | 
            -
             | 
| 83 | 
            -
                it "returns all the artifacts matching the given name" do
         | 
| 84 | 
            -
                  expect(subject.versions("nginx").size).to eq(4)
         | 
| 85 | 
            -
                end
         | 
| 86 | 
            -
             | 
| 87 | 
            -
                it "does not satisfy constraints if it is the default" do
         | 
| 88 | 
            -
                  constraint = Semverse::Constraint.new(Semverse::DEFAULT_CONSTRAINT.to_s)
         | 
| 89 | 
            -
                  expect(constraint).to_not receive(:satisfies?)
         | 
| 90 | 
            -
                  subject.versions("nginx")
         | 
| 91 | 
            -
                end
         | 
| 92 | 
            -
             | 
| 93 | 
            -
                it "returns only matching constraints if one is given" do
         | 
| 94 | 
            -
                  expect(subject.versions("nginx", ">= 3.0.0").size).to eq(2)
         | 
| 95 | 
            -
                end
         | 
| 96 | 
            -
              end
         | 
| 97 | 
            -
             | 
| 98 | 
            -
              describe "==" do
         | 
| 99 | 
            -
                def make_graph
         | 
| 100 | 
            -
                  graph = Solve::Graph.new
         | 
| 101 | 
            -
                  graph.artifact("A" ,"1.0.0").depends("B", "1.0.0")
         | 
| 102 | 
            -
                  graph.artifact("A" ,"2.0.0").depends("C", "1.0.0")
         | 
| 103 | 
            -
                  graph
         | 
| 104 | 
            -
                end
         | 
| 105 | 
            -
             | 
| 106 | 
            -
                subject { make_graph }
         | 
| 107 | 
            -
             | 
| 108 | 
            -
                it "returns false if other isn't a Solve::Graph" do
         | 
| 109 | 
            -
                  expect(subject).to_not eq("chicken")
         | 
| 110 | 
            -
                end
         | 
| 111 | 
            -
             | 
| 112 | 
            -
                it "returns true if the other is the same" do
         | 
| 113 | 
            -
                  expect(subject).to eq(make_graph)
         | 
| 114 | 
            -
                end
         | 
| 115 | 
            -
             | 
| 116 | 
            -
                it "returns false if the other has the same artifacts but different dependencies" do
         | 
| 117 | 
            -
                  other = make_graph
         | 
| 118 | 
            -
                  other.artifact("A", "1.0.0").depends("D", "1.0.0")
         | 
| 119 | 
            -
             | 
| 120 | 
            -
                  expect(subject).to_not eq(other)
         | 
| 121 | 
            -
                end
         | 
| 122 | 
            -
             | 
| 123 | 
            -
                it "returns false if the other has the same dependencies but different artifacts" do
         | 
| 124 | 
            -
                  other = make_graph
         | 
| 125 | 
            -
                  other.artifact("E", "1.0.0")
         | 
| 126 | 
            -
             | 
| 127 | 
            -
                  expect(subject).to_not eq(other)
         | 
| 128 | 
            -
                end
         | 
| 129 | 
            -
              end
         | 
| 130 | 
            -
            end
         | 
| @@ -1,166 +0,0 @@ | |
| 1 | 
            -
            require 'spec_helper'
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            describe Solve::RubySolver do
         | 
| 4 | 
            -
              describe "ClassMethods" do
         | 
| 5 | 
            -
                describe "::timeout" do
         | 
| 6 | 
            -
                  subject { described_class.timeout }
         | 
| 7 | 
            -
             | 
| 8 | 
            -
                  it "returns 30,000 by default" do
         | 
| 9 | 
            -
                    expect(subject).to eql(30_000)
         | 
| 10 | 
            -
                  end
         | 
| 11 | 
            -
             | 
| 12 | 
            -
                  context "when the SOLVE_TIMEOUT env variable is set" do
         | 
| 13 | 
            -
                    before { ENV.stub(:[]).with("SOLVE_TIMEOUT") { "30" } }
         | 
| 14 | 
            -
             | 
| 15 | 
            -
                    it "returns the value multiplied by a thousand" do
         | 
| 16 | 
            -
                      expect(subject).to eql(30_000)
         | 
| 17 | 
            -
                    end
         | 
| 18 | 
            -
                  end
         | 
| 19 | 
            -
                end
         | 
| 20 | 
            -
             | 
| 21 | 
            -
                describe "::activate" do
         | 
| 22 | 
            -
             | 
| 23 | 
            -
                  it "is a no-op" do
         | 
| 24 | 
            -
                    described_class.activate
         | 
| 25 | 
            -
                  end
         | 
| 26 | 
            -
             | 
| 27 | 
            -
                end
         | 
| 28 | 
            -
              end
         | 
| 29 | 
            -
             | 
| 30 | 
            -
              let(:graph) { double(Solve::Graph) }
         | 
| 31 | 
            -
              let(:demands) { [["mysql"], ["nginx"]] }
         | 
| 32 | 
            -
              subject(:solver) { described_class.new(graph, demands, dependency_source: "Berksfile") }
         | 
| 33 | 
            -
             | 
| 34 | 
            -
              it "has a list of demands as ruby literals" do
         | 
| 35 | 
            -
                solver.demands_array.should == demands
         | 
| 36 | 
            -
              end
         | 
| 37 | 
            -
             | 
| 38 | 
            -
              it "has a list of demands as model objects" do
         | 
| 39 | 
            -
                expected = [
         | 
| 40 | 
            -
                  Solve::Demand.new(solver, "mysql"),
         | 
| 41 | 
            -
                  Solve::Demand.new(solver, "nginx")
         | 
| 42 | 
            -
                ]
         | 
| 43 | 
            -
                solver.demands.should == expected
         | 
| 44 | 
            -
              end
         | 
| 45 | 
            -
             | 
| 46 | 
            -
              it "has a graph" do
         | 
| 47 | 
            -
                solver.graph.should == graph
         | 
| 48 | 
            -
              end
         | 
| 49 | 
            -
             | 
| 50 | 
            -
              describe "when the constraints are solvable" do
         | 
| 51 | 
            -
                let(:graph) do
         | 
| 52 | 
            -
                  graph = Solve::Graph.new
         | 
| 53 | 
            -
                  graph.artifact("A", "1.0.0")
         | 
| 54 | 
            -
                  graph.artifact("B", "1.0.0").depends("A")
         | 
| 55 | 
            -
                  graph
         | 
| 56 | 
            -
                end
         | 
| 57 | 
            -
             | 
| 58 | 
            -
                let(:demands) { [["A"], ["B"]] }
         | 
| 59 | 
            -
             | 
| 60 | 
            -
                it "gives the solution as a Hash" do
         | 
| 61 | 
            -
                  solver.resolve.should == {"A"=>"1.0.0", "B"=>"1.0.0"}
         | 
| 62 | 
            -
                end
         | 
| 63 | 
            -
             | 
| 64 | 
            -
                it "gives the solution in sorted form" do
         | 
| 65 | 
            -
                  solver.resolve(sorted: true).should == [["A", "1.0.0"], ["B", "1.0.0"]]
         | 
| 66 | 
            -
                end
         | 
| 67 | 
            -
              end
         | 
| 68 | 
            -
             | 
| 69 | 
            -
              describe "when the constraints are not solvable" do
         | 
| 70 | 
            -
                let(:error) do
         | 
| 71 | 
            -
                  begin
         | 
| 72 | 
            -
                    solver.resolve
         | 
| 73 | 
            -
                  rescue => e
         | 
| 74 | 
            -
                    e
         | 
| 75 | 
            -
                  else
         | 
| 76 | 
            -
                    raise "Expected resolve to cause an error"
         | 
| 77 | 
            -
                  end
         | 
| 78 | 
            -
                end
         | 
| 79 | 
            -
             | 
| 80 | 
            -
                context "and molinillo identifies missing artifacts" do
         | 
| 81 | 
            -
                  let(:graph) do
         | 
| 82 | 
            -
                    graph = Solve::Graph.new
         | 
| 83 | 
            -
                    graph.artifact("A", "1.0.0")
         | 
| 84 | 
            -
                    graph
         | 
| 85 | 
            -
                  end
         | 
| 86 | 
            -
             | 
| 87 | 
            -
                  let(:demands) { [ ["Z"] ] }
         | 
| 88 | 
            -
             | 
| 89 | 
            -
                  it "raises an error detailing the missing artifacts" do
         | 
| 90 | 
            -
                    expect(error).to be_a_kind_of(Solve::Errors::NoSolutionError)
         | 
| 91 | 
            -
                    expected_error = <<-ERROR_MESSAGE
         | 
| 92 | 
            -
            Unable to satisfy the following requirements:
         | 
| 93 | 
            -
             | 
| 94 | 
            -
            - `Z (>= 0.0.0)` required by `Berksfile`
         | 
| 95 | 
            -
            ERROR_MESSAGE
         | 
| 96 | 
            -
                    expect(error.to_s).to eq(expected_error)
         | 
| 97 | 
            -
                  end
         | 
| 98 | 
            -
                end
         | 
| 99 | 
            -
             | 
| 100 | 
            -
                context "and molinillo identifies constraints that exclude all known versions" do
         | 
| 101 | 
            -
                  let(:graph) do
         | 
| 102 | 
            -
                    graph = Solve::Graph.new
         | 
| 103 | 
            -
                    graph.artifact("A", "1.0.0")
         | 
| 104 | 
            -
                    graph
         | 
| 105 | 
            -
                  end
         | 
| 106 | 
            -
             | 
| 107 | 
            -
                  let(:demands) { [ ["A", "> 1.0.0"] ] }
         | 
| 108 | 
            -
             | 
| 109 | 
            -
                  it "raises an error detailing the missing artifacts" do
         | 
| 110 | 
            -
                    expect(error).to be_a_kind_of(Solve::Errors::NoSolutionError)
         | 
| 111 | 
            -
                    expected_error = <<-ERROR_MESSAGE
         | 
| 112 | 
            -
            Unable to satisfy the following requirements:
         | 
| 113 | 
            -
             | 
| 114 | 
            -
            - `A (> 1.0.0)` required by `Berksfile`
         | 
| 115 | 
            -
            ERROR_MESSAGE
         | 
| 116 | 
            -
                    expect(error.to_s).to eq(expected_error)
         | 
| 117 | 
            -
                  end
         | 
| 118 | 
            -
                end
         | 
| 119 | 
            -
             | 
| 120 | 
            -
                context "and molinillo identifies dependency conflicts" do
         | 
| 121 | 
            -
                  let(:graph) do
         | 
| 122 | 
            -
                    graph = Solve::Graph.new
         | 
| 123 | 
            -
                    graph.artifact("A", "1.0.0").depends("B").depends("C")
         | 
| 124 | 
            -
                    graph.artifact("B", "1.0.0").depends("D", "= 1.0.0")
         | 
| 125 | 
            -
                    graph.artifact("C", "1.0.0").depends("D", "= 2.0.0")
         | 
| 126 | 
            -
                    graph.artifact("D", "1.0.0")
         | 
| 127 | 
            -
                    graph.artifact("D", "2.0.0")
         | 
| 128 | 
            -
                    graph
         | 
| 129 | 
            -
                  end
         | 
| 130 | 
            -
             | 
| 131 | 
            -
                  let(:demands) { [ [ "A" ] ] }
         | 
| 132 | 
            -
             | 
| 133 | 
            -
                  it "raises an error detailing the missing artifacts" do
         | 
| 134 | 
            -
                    expect(error).to be_a_kind_of(Solve::Errors::NoSolutionError)
         | 
| 135 | 
            -
                    expected_error = <<-ERROR_MESSAGE
         | 
| 136 | 
            -
            Unable to satisfy the following requirements:
         | 
| 137 | 
            -
             | 
| 138 | 
            -
            - `D (= 1.0.0)` required by `B-1.0.0`
         | 
| 139 | 
            -
            - `D (= 2.0.0)` required by `C-1.0.0`
         | 
| 140 | 
            -
            ERROR_MESSAGE
         | 
| 141 | 
            -
                    expect(error.to_s).to eq(expected_error)
         | 
| 142 | 
            -
                  end
         | 
| 143 | 
            -
                end
         | 
| 144 | 
            -
              end
         | 
| 145 | 
            -
             | 
| 146 | 
            -
              describe "supporting Serializer interface" do
         | 
| 147 | 
            -
                let(:serializer) { Solve::Solver::Serializer.new }
         | 
| 148 | 
            -
             | 
| 149 | 
            -
                before do
         | 
| 150 | 
            -
                  graph.stub(:artifacts).and_return([])
         | 
| 151 | 
            -
                end
         | 
| 152 | 
            -
             | 
| 153 | 
            -
                it "implements the required interface" do
         | 
| 154 | 
            -
                  problem = Solve::Problem.from_solver(solver)
         | 
| 155 | 
            -
                  json_string = serializer.serialize(problem)
         | 
| 156 | 
            -
                  problem_data = JSON.parse(json_string)
         | 
| 157 | 
            -
                  expected_demands = [
         | 
| 158 | 
            -
                    {"name" => "mysql", "constraint" => ">= 0.0.0"},
         | 
| 159 | 
            -
                    {"name" => "nginx", "constraint" => ">= 0.0.0"}
         | 
| 160 | 
            -
                  ]
         | 
| 161 | 
            -
             | 
| 162 | 
            -
                  problem_data["demands"].should =~ expected_demands
         | 
| 163 | 
            -
                end
         | 
| 164 | 
            -
              end
         | 
| 165 | 
            -
            end
         | 
| 166 | 
            -
             | 
| @@ -1,33 +0,0 @@ | |
| 1 | 
            -
            require 'spec_helper'
         | 
| 2 | 
            -
            require 'solve/ruby_solver'
         | 
| 3 | 
            -
             | 
| 4 | 
            -
            describe Solve::Solver::Serializer do
         | 
| 5 | 
            -
             | 
| 6 | 
            -
              let(:graph) do
         | 
| 7 | 
            -
                Solve::Graph.new.tap do |g|
         | 
| 8 | 
            -
                  g.artifact("A", "1.0.0").depends("B", "1.0.0")
         | 
| 9 | 
            -
                  g.artifact("B", "1.0.0").depends("C", "1.0.0")
         | 
| 10 | 
            -
                  g.artifact("C", "1.0.0")
         | 
| 11 | 
            -
                end
         | 
| 12 | 
            -
              end
         | 
| 13 | 
            -
             | 
| 14 | 
            -
              let(:demands) { [["A", "1.0.0"]] }
         | 
| 15 | 
            -
             | 
| 16 | 
            -
              let(:serializer) { Solve::Solver::Serializer.new }
         | 
| 17 | 
            -
             | 
| 18 | 
            -
              it "deserializes a serialized problem to an equivalent problem" do
         | 
| 19 | 
            -
                problem = Solve::Problem.new(graph, demands)
         | 
| 20 | 
            -
                serialized = serializer.serialize(problem)
         | 
| 21 | 
            -
                deserialized = serializer.deserialize(serialized)
         | 
| 22 | 
            -
             | 
| 23 | 
            -
                problem.graph.should eql(deserialized.graph)
         | 
| 24 | 
            -
                problem.demands.should eql(deserialized.demands)
         | 
| 25 | 
            -
              end
         | 
| 26 | 
            -
             | 
| 27 | 
            -
              it "creates a problem from a solver" do
         | 
| 28 | 
            -
                solver = Solve::RubySolver.new(graph, demands)
         | 
| 29 | 
            -
                problem = Solve::Problem.from_solver(solver)
         | 
| 30 | 
            -
                expect(problem.demands).to eq([["A", "= 1.0.0"]])
         | 
| 31 | 
            -
                expect(problem.graph).to eq(graph)
         | 
| 32 | 
            -
              end
         | 
| 33 | 
            -
            end
         | 
    
        data/spec/unit/solve_spec.rb
    DELETED
    
    | @@ -1,19 +0,0 @@ | |
| 1 | 
            -
            require 'spec_helper'
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            describe Solve do
         | 
| 4 | 
            -
              describe "ClassMethods" do
         | 
| 5 | 
            -
                subject { Solve }
         | 
| 6 | 
            -
             | 
| 7 | 
            -
                describe "#it" do
         | 
| 8 | 
            -
                  it "returns nil if a solution does not exist" do
         | 
| 9 | 
            -
                    skip
         | 
| 10 | 
            -
                  end
         | 
| 11 | 
            -
                end
         | 
| 12 | 
            -
             | 
| 13 | 
            -
                describe "#it!" do
         | 
| 14 | 
            -
                  it "raises NoSolutionError if a solution does not exist" do
         | 
| 15 | 
            -
                    skip
         | 
| 16 | 
            -
                  end
         | 
| 17 | 
            -
                end
         | 
| 18 | 
            -
              end
         | 
| 19 | 
            -
            end
         |