diff --git a/pkg/solver/decoder.go b/pkg/solver/decoder.go index bcb4d531..5781a5a7 100644 --- a/pkg/solver/decoder.go +++ b/pkg/solver/decoder.go @@ -22,7 +22,7 @@ import ( "unicode" pkg "github.com/mudler/luet/pkg/package" - "github.com/philopon/go-toposort" + toposort "github.com/philopon/go-toposort" "github.com/stevenle/topsort" ) @@ -88,7 +88,7 @@ func (assertions PackagesAssertions) EnsureOrder() PackagesAssertions { fingerprints = append(fingerprints, a.Package.GetFingerPrint()) unorderedAssertions = append(unorderedAssertions, a) // Build a list of the ones that must be ordered - if a.Package.Flagged() && a.Value { + if a.Value { unorderedAssertions = append(unorderedAssertions, a) // Build a list of the ones that must be ordered } else { orderedAssertions = append(orderedAssertions, a) // Keep last the ones which are not meant to be installed @@ -137,7 +137,7 @@ func (assertions PackagesAssertions) Order(fingerprint string) PackagesAssertion fingerprints = append(fingerprints, a.Package.GetFingerPrint()) unorderedAssertions = append(unorderedAssertions, a) // Build a list of the ones that must be ordered - if a.Package.Flagged() && a.Value { + if a.Value { unorderedAssertions = append(unorderedAssertions, a) // Build a list of the ones that must be ordered } else { orderedAssertions = append(orderedAssertions, a) // Keep last the ones which are not meant to be installed @@ -215,7 +215,7 @@ func (a PackagesAssertions) Less(i, j int) bool { func (assertions PackagesAssertions) AssertionHash() string { var fingerprint string for _, assertion := range assertions { // Note: Always order them first! - if assertion.Value && assertion.Package.Flagged() { // Tke into account only dependencies installed (get fingerprint of subgraph) + if assertion.Value { // Tke into account only dependencies installed (get fingerprint of subgraph) fingerprint += assertion.ToString() + "\n" } } diff --git a/pkg/solver/decoder_test.go b/pkg/solver/decoder_test.go index cfebaf7e..a9c80ac3 100644 --- a/pkg/solver/decoder_test.go +++ b/pkg/solver/decoder_test.go @@ -26,11 +26,22 @@ import ( ) var _ = Describe("Decoder", func() { + db := pkg.NewInMemoryDatabase(false) + dbInstalled := pkg.NewInMemoryDatabase(false) + dbDefinitions := pkg.NewInMemoryDatabase(false) + s := NewSolver(dbInstalled, dbDefinitions, db) + + BeforeEach(func() { + db = pkg.NewInMemoryDatabase(false) + dbInstalled = pkg.NewInMemoryDatabase(false) + dbDefinitions = pkg.NewInMemoryDatabase(false) + s = NewSolver(dbInstalled, dbDefinitions, db) + }) + Context("Assertion ordering", func() { eq := 0 for index := 0; index < 300; index++ { // Just to make sure we don't have false positives It("Orders them correctly #"+strconv.Itoa(index), func() { - db := pkg.NewInMemoryDatabase(false) C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) E := pkg.NewPackage("E", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) @@ -41,15 +52,23 @@ var _ = Describe("Decoder", func() { B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - s := NewSolver([]pkg.Package{C}, []pkg.Package{A, B, C, D, E, F, G}, db) + for _, p := range []pkg.Package{A, B, C, D, E, F, G} { + _, err := dbDefinitions.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + + for _, p := range []pkg.Package{C} { + _, err := dbInstalled.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } solution, err := s.Install([]pkg.Package{A}) - Expect(solution).To(ContainElement(PackageAssert{Package: A.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: B.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: C.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: H.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: G.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: H, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: G, Value: true})) Expect(len(solution)).To(Equal(6)) Expect(err).ToNot(HaveOccurred()) @@ -73,7 +92,6 @@ var _ = Describe("Decoder", func() { equality := 0 for index := 0; index < 300; index++ { // Just to make sure we don't have false positives It("Doesn't order them correctly otherwise #"+strconv.Itoa(index), func() { - db := pkg.NewInMemoryDatabase(false) C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) E := pkg.NewPackage("E", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) @@ -84,15 +102,23 @@ var _ = Describe("Decoder", func() { B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - s := NewSolver([]pkg.Package{C}, []pkg.Package{A, B, C, D, E, F, G}, db) + for _, p := range []pkg.Package{A, B, C, D, E, F, G} { + _, err := dbDefinitions.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + + for _, p := range []pkg.Package{C} { + _, err := dbInstalled.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } solution, err := s.Install([]pkg.Package{A}) - Expect(solution).To(ContainElement(PackageAssert{Package: A.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: B.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: C.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: H.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: G.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: H, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: G, Value: true})) Expect(len(solution)).To(Equal(6)) Expect(err).ToNot(HaveOccurred()) @@ -132,7 +158,6 @@ var _ = Describe("Decoder", func() { Context("Assertion hashing", func() { It("Hashes them, and could be used for comparison", func() { - db := pkg.NewInMemoryDatabase(false) C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) E := pkg.NewPackage("E", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) @@ -143,15 +168,23 @@ var _ = Describe("Decoder", func() { B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - s := NewSolver([]pkg.Package{C}, []pkg.Package{A, B, C, D, E, F, G}, db) + for _, p := range []pkg.Package{A, B, C, D, E, F, G} { + _, err := dbDefinitions.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + + for _, p := range []pkg.Package{C} { + _, err := dbInstalled.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } solution, err := s.Install([]pkg.Package{A}) - Expect(solution).To(ContainElement(PackageAssert{Package: A.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: B.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: C.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: H.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: G.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: H, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: G, Value: true})) Expect(len(solution)).To(Equal(6)) Expect(err).ToNot(HaveOccurred()) @@ -165,11 +198,11 @@ var _ = Describe("Decoder", func() { hash := solution.AssertionHash() solution, err = s.Install([]pkg.Package{B}) - Expect(solution).To(ContainElement(PackageAssert{Package: B.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: C.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: H.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: G.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: H, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: G, Value: true})) Expect(len(solution)).To(Equal(6)) Expect(err).ToNot(HaveOccurred()) @@ -183,18 +216,29 @@ var _ = Describe("Decoder", func() { Expect(solution[3].Package.GetName()).To(Equal("D")) Expect(solution[4].Package.GetName()).To(Equal("B")) Expect(solution[0].Value).ToNot(BeTrue()) - Expect(solution[0].Package.Flagged()).To(BeTrue()) Expect(hash).ToNot(Equal("")) Expect(hash2).ToNot(Equal("")) Expect(hash != hash2).To(BeTrue()) - db2 := pkg.NewInMemoryDatabase(false) + + }) + It("Hashes them, and could be used for comparison", func() { X := pkg.NewPackage("X", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) Y := pkg.NewPackage("Y", "", []*pkg.DefaultPackage{X}, []*pkg.DefaultPackage{}) Z := pkg.NewPackage("Z", "", []*pkg.DefaultPackage{X}, []*pkg.DefaultPackage{}) - s = NewSolver([]pkg.Package{}, []pkg.Package{X, Y, Z}, db2) - solution, err = s.Install([]pkg.Package{Y}) + + for _, p := range []pkg.Package{X, Y, Z} { + _, err := dbDefinitions.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + + for _, p := range []pkg.Package{} { + _, err := dbInstalled.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + + solution, err := s.Install([]pkg.Package{Y}) Expect(err).ToNot(HaveOccurred()) solution2, err := s.Install([]pkg.Package{Z}) diff --git a/pkg/solver/solver.go b/pkg/solver/solver.go index ba22d117..3a98623d 100644 --- a/pkg/solver/solver.go +++ b/pkg/solver/solver.go @@ -16,9 +16,11 @@ package solver import ( - "errors" "sort" + //. "github.com/mudler/luet/pkg/logger" + "github.com/pkg/errors" + "github.com/crillab/gophersat/bf" version "github.com/hashicorp/go-version" pkg "github.com/mudler/luet/pkg/package" @@ -26,32 +28,57 @@ import ( // PackageSolver is an interface to a generic package solving algorithm type PackageSolver interface { - SetWorld(p []pkg.Package) + SetDefinitionDatabase(pkg.PackageDatabase) Install(p []pkg.Package) (PackagesAssertions, error) Uninstall(candidate pkg.Package) ([]pkg.Package, error) ConflictsWithInstalled(p pkg.Package) (bool, error) ConflictsWith(p pkg.Package, ls []pkg.Package) (bool, error) Best([]pkg.Package) pkg.Package + World() []pkg.Package } // Solver is the default solver for luet type Solver struct { - SolverDatabase pkg.PackageDatabase - Wanted []pkg.Package - Installed []pkg.Package - World []pkg.Package + DefinitionDatabase pkg.PackageDatabase + SolverDatabase pkg.PackageDatabase + Wanted []pkg.Package + InstalledDatabase pkg.PackageDatabase } // NewSolver accepts as argument two lists of packages, the first is the initial set, // the second represent all the known packages. -func NewSolver(init []pkg.Package, w []pkg.Package, solverdb pkg.PackageDatabase) PackageSolver { - for _, v := range init { - pkg.NormalizeFlagged(v) - } - for _, v := range w { - pkg.NormalizeFlagged(v) - } - return &Solver{Installed: init, World: w, SolverDatabase: solverdb} +func NewSolver(installed pkg.PackageDatabase, definitiondb pkg.PackageDatabase, solverdb pkg.PackageDatabase) PackageSolver { + // inst := pkg.NewInMemoryDatabase(false) + // def := pkg.NewInMemoryDatabase(false) + // // // FIXME: This should all be locked in the db - for now forbid the solver to be run in threads. + // for _, k := range installed.GetPackages() { + // pack, err := installed.GetPackage(k) + // if err == nil { + // inst.CreatePackage(pack) + // } + // } + // for _, k := range definitiondb.GetPackages() { + // pack, err := definitiondb.GetPackage(k) + // if err == nil { + // def.CreatePackage(pack) + // } + // } + // // FIXME: + // for _, k := range inst.GetPackages() { + // pack, err := inst.GetPackage(k) + // if err == nil { + + // pkg.NormalizeFlagged(inst, pack) + // } + // } + // for _, k := range def.GetPackages() { + // pack, err := def.GetPackage(k) + // if err == nil { + + // pkg.NormalizeFlagged(def, pack) + // } + // } + return &Solver{InstalledDatabase: installed, DefinitionDatabase: definitiondb, SolverDatabase: solverdb} } // TODO: []pkg.Package should have its own type with this kind of methods in (+Unique, sort, etc.) @@ -81,12 +108,36 @@ func (s *Solver) Best(set []pkg.Package) pkg.Package { // SetWorld is a setter for the list of all known packages to the solver -func (s *Solver) SetWorld(p []pkg.Package) { - s.World = p +func (s *Solver) SetDefinitionDatabase(db pkg.PackageDatabase) { + s.DefinitionDatabase = db +} + +func (s *Solver) World() []pkg.Package { + var all []pkg.Package + // FIXME: This should all be locked in the db - for now forbid the solver to be run in threads. + for _, k := range s.DefinitionDatabase.GetPackages() { + pack, err := s.DefinitionDatabase.GetPackage(k) + if err == nil { + all = append(all, pack) + } + } + return all +} + +func (s *Solver) Installed() []pkg.Package { + var all []pkg.Package + // FIXME: This should all be locked in the db - for now forbid the solver to be run in threads. + for _, k := range s.InstalledDatabase.GetPackages() { + pack, err := s.InstalledDatabase.GetPackage(k) + if err == nil { + all = append(all, pack) + } + } + return all } func (s *Solver) noRulesWorld() bool { - for _, p := range s.World { + for _, p := range s.World() { if len(p.GetConflicts()) != 0 || len(p.GetRequires()) != 0 { return false } @@ -97,8 +148,8 @@ func (s *Solver) noRulesWorld() bool { func (s *Solver) BuildInstalled() (bf.Formula, error) { var formulas []bf.Formula - for _, p := range s.Installed { - solvable, err := p.BuildFormula(s.SolverDatabase) + for _, p := range s.Installed() { + solvable, err := p.BuildFormula(s.DefinitionDatabase, s.SolverDatabase) if err != nil { return nil, err } @@ -124,8 +175,8 @@ func (s *Solver) BuildWorld(includeInstalled bool) (bf.Formula, error) { formulas = append(formulas, solvable) } - for _, p := range s.World { - solvable, err := p.BuildFormula(s.SolverDatabase) + for _, p := range s.World() { + solvable, err := p.BuildFormula(s.DefinitionDatabase, s.SolverDatabase) if err != nil { return nil, err } @@ -134,15 +185,42 @@ func (s *Solver) BuildWorld(includeInstalled bool) (bf.Formula, error) { return bf.And(formulas...), nil } -func (s *Solver) ConflictsWith(p pkg.Package, ls []pkg.Package) (bool, error) { - pkg.NormalizeFlagged(p) +func (s *Solver) getList(db pkg.PackageDatabase, lsp []pkg.Package) ([]pkg.Package, error) { + var ls []pkg.Package + for _, pp := range lsp { + cp, err := db.FindPackage(pp) + if err != nil { + cp = pp //Relax search, otherwise we cannot compute solutions for packages not in definitions + + //return nil, errors.Wrap(err, "Package not found in db") + } + ls = append(ls, cp) + } + return ls, nil +} + +func (s *Solver) ConflictsWith(pack pkg.Package, lsp []pkg.Package) (bool, error) { + p, err := s.DefinitionDatabase.FindPackage(pack) + if err != nil { + p = pack //Relax search, otherwise we cannot compute solutions for packages not in definitions + + // return false, errors.Wrap(err, "Package not found in definition db") + } + + ls, err := s.getList(s.DefinitionDatabase, lsp) + if err != nil { + return false, errors.Wrap(err, "Package not found in definition db") + } + + // TODO: Needs to be find in package def before encoding! + // pkg.NormalizeFlagged(s.DefinitionDatabase, p) var formulas []bf.Formula if s.noRulesWorld() { return false, nil } - encodedP, err := p.IsFlagged(true).Encode(s.SolverDatabase) + encodedP, err := p.Encode(s.SolverDatabase) if err != nil { return false, err } @@ -181,33 +259,45 @@ func (s *Solver) ConflictsWith(p pkg.Package, ls []pkg.Package) (bool, error) { } func (s *Solver) ConflictsWithInstalled(p pkg.Package) (bool, error) { - return s.ConflictsWith(p, s.Installed) + return s.ConflictsWith(p, s.Installed()) } // Uninstall takes a candidate package and return a list of packages that would be removed // in order to purge the candidate. Returns error if unsat. -func (s *Solver) Uninstall(candidate pkg.Package) ([]pkg.Package, error) { +func (s *Solver) Uninstall(c pkg.Package) ([]pkg.Package, error) { var res []pkg.Package - + candidate, err := s.InstalledDatabase.FindPackage(c) + if err != nil { + candidate = c //Relax search, otherwise we cannot compute solutions for packages not in definitions + // return nil, errors.Wrap(err, "Package not found between installed") + } // Build a fake "Installed" - Candidate and its requires tree var InstalledMinusCandidate []pkg.Package - for _, i := range s.Installed { - if !i.Matches(candidate) && !candidate.RequiresContains(i) { - InstalledMinusCandidate = append(InstalledMinusCandidate, i) + + // TODO: Can be optimized + for _, i := range s.Installed() { + if !i.Matches(candidate) { + contains, err := candidate.RequiresContains(s.SolverDatabase, i) + if err != nil { + return nil, errors.Wrap(err, "Failed getting installed list") + } + if !contains { + InstalledMinusCandidate = append(InstalledMinusCandidate, i) + } } } // Get the requirements to install the candidate - saved := s.Installed - s.Installed = []pkg.Package{} + saved := s.InstalledDatabase + s.InstalledDatabase = pkg.NewInMemoryDatabase(false) asserts, err := s.Install([]pkg.Package{candidate}) if err != nil { return nil, err } - s.Installed = saved + s.InstalledDatabase = saved for _, a := range asserts { - if a.Value && a.Package.Flagged() { + if a.Value { c, err := s.ConflictsWithInstalled(a.Package) if err != nil { @@ -249,13 +339,14 @@ func (s *Solver) BuildFormula() (bf.Formula, error) { return nil, err } W := bf.Var(encodedW) - - if len(s.Installed) == 0 { + installedWorld := s.Installed() + //TODO:Optimize + if len(installedWorld) == 0 { formulas = append(formulas, W) //bf.And(bf.True, W)) continue } - for _, installed := range s.Installed { + for _, installed := range installedWorld { encodedI, err := installed.Encode(s.SolverDatabase) if err != nil { return nil, err @@ -297,23 +388,23 @@ func (s *Solver) Solve() (PackagesAssertions, error) { // Install given a list of packages, returns package assertions to indicate the packages that must be installed in the system in order // to statisfy all the constraints -func (s *Solver) Install(coll []pkg.Package) (PackagesAssertions, error) { - for _, v := range coll { - v.IsFlagged(false) +func (s *Solver) Install(c []pkg.Package) (PackagesAssertions, error) { + + coll, err := s.getList(s.DefinitionDatabase, c) + if err != nil { + return nil, errors.Wrap(err, "Packages not found in definition db") } + s.Wanted = coll if s.noRulesWorld() { var ass PackagesAssertions - for _, p := range s.Installed { - pp := p.IsFlagged(true) - ass = append(ass, PackageAssert{Package: pp.(*pkg.DefaultPackage), Value: true}) + for _, p := range s.Installed() { + ass = append(ass, PackageAssert{Package: p.(*pkg.DefaultPackage), Value: true}) } for _, p := range s.Wanted { - pp := p.IsFlagged(true) - - ass = append(ass, PackageAssert{Package: pp.(*pkg.DefaultPackage), Value: true}) + ass = append(ass, PackageAssert{Package: p.(*pkg.DefaultPackage), Value: true}) } return ass, nil } diff --git a/pkg/solver/solver_test.go b/pkg/solver/solver_test.go index 8fffa2a6..a5db9033 100644 --- a/pkg/solver/solver_test.go +++ b/pkg/solver/solver_test.go @@ -17,7 +17,6 @@ package solver_test import ( pkg "github.com/mudler/luet/pkg/package" - "github.com/mudler/luet/pkg/solver" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -26,38 +25,66 @@ import ( var _ = Describe("Solver", func() { + db := pkg.NewInMemoryDatabase(false) + dbInstalled := pkg.NewInMemoryDatabase(false) + dbDefinitions := pkg.NewInMemoryDatabase(false) + s := NewSolver(dbInstalled, dbDefinitions, db) + + BeforeEach(func() { + db = pkg.NewInMemoryDatabase(false) + dbInstalled = pkg.NewInMemoryDatabase(false) + dbDefinitions = pkg.NewInMemoryDatabase(false) + s = NewSolver(dbInstalled, dbDefinitions, db) + }) Context("Simple set", func() { It("Solves correctly if the selected package has no requirements or conflicts and we have nothing installed yet", func() { - db := pkg.NewInMemoryDatabase(false) B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - s := NewSolver([]pkg.Package{}, []pkg.Package{A, B, C}, db) + for _, p := range []pkg.Package{A, B, C} { + _, err := dbDefinitions.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + + for _, p := range []pkg.Package{} { + _, err := dbInstalled.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + s = NewSolver(dbInstalled, dbDefinitions, db) + solution, err := s.Install([]pkg.Package{A}) Expect(err).ToNot(HaveOccurred()) - Expect(solution).To(ContainElement(PackageAssert{Package: A.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) Expect(len(solution)).To(Equal(1)) }) It("Solves correctly if the selected package has no requirements or conflicts and we have installed one package", func() { - db := pkg.NewInMemoryDatabase(false) B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - s := NewSolver([]pkg.Package{C}, []pkg.Package{A, B, C}, db) + for _, p := range []pkg.Package{A, B, C} { + _, err := dbDefinitions.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + + for _, p := range []pkg.Package{C} { + _, err := dbInstalled.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + s = NewSolver(dbInstalled, dbDefinitions, db) + solution, err := s.Install([]pkg.Package{B}) Expect(err).ToNot(HaveOccurred()) - Expect(solution).To(ContainElement(PackageAssert{Package: B.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: C.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) Expect(len(solution)).To(Equal(2)) }) It("Solves correctly if the selected package to install has no requirement or conflicts, but in the world there is one with a requirement", func() { - db := pkg.NewInMemoryDatabase(false) B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) @@ -65,72 +92,107 @@ var _ = Describe("Solver", func() { D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) E := pkg.NewPackage("E", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - s := NewSolver([]pkg.Package{E, C}, []pkg.Package{A, B, C, D, E}, db) + for _, p := range []pkg.Package{A, B, C, D, E} { + _, err := dbDefinitions.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + + for _, p := range []pkg.Package{E, C} { + _, err := dbInstalled.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + s = NewSolver(dbInstalled, dbDefinitions, db) + solution, err := s.Install([]pkg.Package{A}) Expect(err).ToNot(HaveOccurred()) - Expect(solution).To(ContainElement(PackageAssert{Package: A.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: C.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: E.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: B.IsFlagged(true).(*pkg.DefaultPackage), Value: false})) - Expect(solution).To(ContainElement(PackageAssert{Package: D.IsFlagged(true).(*pkg.DefaultPackage), Value: false})) + Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: E, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: false})) + Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: false})) Expect(len(solution)).To(Equal(5)) }) It("Solves correctly if the selected package to install has requirements", func() { - db := pkg.NewInMemoryDatabase(false) B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) - s := NewSolver([]pkg.Package{C}, []pkg.Package{A, B, C, D}, db) + for _, p := range []pkg.Package{A, B, C, D} { + _, err := dbDefinitions.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + + for _, p := range []pkg.Package{C} { + _, err := dbInstalled.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + s = NewSolver(dbInstalled, dbDefinitions, db) + solution, err := s.Install([]pkg.Package{A}) Expect(err).ToNot(HaveOccurred()) - Expect(solution).To(ContainElement(PackageAssert{Package: A.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: C.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true})) Expect(len(solution)).To(Equal(3)) }) It("Solves correctly", func() { - db := pkg.NewInMemoryDatabase(false) B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - s := NewSolver([]pkg.Package{C}, []pkg.Package{A, B, C}, db) + for _, p := range []pkg.Package{A, B, C} { + _, err := dbDefinitions.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + + for _, p := range []pkg.Package{C} { + _, err := dbInstalled.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + s = NewSolver(dbInstalled, dbDefinitions, db) + solution, err := s.Install([]pkg.Package{A}) Expect(err).ToNot(HaveOccurred()) - Expect(solution).To(ContainElement(PackageAssert{Package: A.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: B.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: C.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) Expect(len(solution)).To(Equal(3)) }) It("Solves correctly more complex ones", func() { - db := pkg.NewInMemoryDatabase(false) C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - s := NewSolver([]pkg.Package{C}, []pkg.Package{A, B, C, D}, db) + for _, p := range []pkg.Package{A, B, C, D} { + _, err := dbDefinitions.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + + for _, p := range []pkg.Package{C} { + _, err := dbInstalled.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + s = NewSolver(dbInstalled, dbDefinitions, db) solution, err := s.Install([]pkg.Package{A}) - Expect(solution).To(ContainElement(PackageAssert{Package: A.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: B.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: C.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) Expect(len(solution)).To(Equal(4)) Expect(err).ToNot(HaveOccurred()) }) It("Solves correctly more complex ones", func() { - db := pkg.NewInMemoryDatabase(false) E := pkg.NewPackage("E", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) @@ -138,37 +200,53 @@ var _ = Describe("Solver", func() { B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - s := NewSolver([]pkg.Package{}, []pkg.Package{A, B, C, D, E}, db) + for _, p := range []pkg.Package{A, B, C, D, E} { + _, err := dbDefinitions.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + + for _, p := range []pkg.Package{} { + _, err := dbInstalled.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + s = NewSolver(dbInstalled, dbDefinitions, db) solution, err := s.Install([]pkg.Package{A}) - Expect(solution).To(ContainElement(PackageAssert{Package: A.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: B.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true})) Expect(len(solution)).To(Equal(3)) Expect(err).ToNot(HaveOccurred()) }) It("Uninstalls simple package correctly", func() { - db := pkg.NewInMemoryDatabase(false) C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - s := NewSolver([]pkg.Package{A, B, C, D}, []pkg.Package{A, B, C, D}, db) + for _, p := range []pkg.Package{A, B, C, D} { + _, err := dbDefinitions.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + + for _, p := range []pkg.Package{A, B, C, D} { + _, err := dbInstalled.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + s = NewSolver(dbInstalled, dbDefinitions, db) solution, err := s.Uninstall(A) Expect(err).ToNot(HaveOccurred()) Expect(solution).To(ContainElement(A.IsFlagged(false))) - // Expect(solution).To(ContainElement(PackageAssert{Package: C.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) + // Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) Expect(len(solution)).To(Equal(1)) }) It("Find conflicts", func() { - db := pkg.NewInMemoryDatabase(false) C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) @@ -176,7 +254,16 @@ var _ = Describe("Solver", func() { B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{A}, []*pkg.DefaultPackage{}) - s := NewSolver([]pkg.Package{A, B, C, D}, []pkg.Package{A, B, C, D}, db) + for _, p := range []pkg.Package{A, B, C, D} { + _, err := dbDefinitions.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + + for _, p := range []pkg.Package{A, B, C, D} { + _, err := dbInstalled.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + val, err := s.ConflictsWithInstalled(A) Expect(err).ToNot(HaveOccurred()) Expect(val).To(BeTrue()) @@ -184,7 +271,6 @@ var _ = Describe("Solver", func() { }) It("Find nested conflicts", func() { - db := pkg.NewInMemoryDatabase(false) C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) @@ -192,14 +278,22 @@ var _ = Describe("Solver", func() { B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{A}, []*pkg.DefaultPackage{}) - s := NewSolver([]pkg.Package{A, B, C, D}, []pkg.Package{A, B, C, D}, db) + for _, p := range []pkg.Package{A, B, C, D} { + _, err := dbDefinitions.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + + for _, p := range []pkg.Package{A, B, C, D} { + _, err := dbInstalled.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + val, err := s.ConflictsWithInstalled(D) Expect(err).ToNot(HaveOccurred()) Expect(val).To(BeTrue()) }) It("Doesn't find nested conflicts", func() { - db := pkg.NewInMemoryDatabase(false) C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) @@ -207,14 +301,22 @@ var _ = Describe("Solver", func() { B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{A}, []*pkg.DefaultPackage{}) - s := NewSolver([]pkg.Package{A, B, C, D}, []pkg.Package{A, B, C, D}, db) + for _, p := range []pkg.Package{A, B, C, D} { + _, err := dbDefinitions.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + + for _, p := range []pkg.Package{A, B, C, D} { + _, err := dbInstalled.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + val, err := s.ConflictsWithInstalled(C) Expect(err).ToNot(HaveOccurred()) Expect(val).ToNot(BeTrue()) }) It("Doesn't find conflicts", func() { - db := pkg.NewInMemoryDatabase(false) C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) @@ -222,40 +324,59 @@ var _ = Describe("Solver", func() { B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - s := NewSolver([]pkg.Package{A, B, C, D}, []pkg.Package{A, B, C, D}, db) + for _, p := range []pkg.Package{A, B, C, D} { + _, err := dbDefinitions.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + + for _, p := range []pkg.Package{A, B, C, D} { + _, err := dbInstalled.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } val, err := s.ConflictsWithInstalled(C) Expect(err).ToNot(HaveOccurred()) Expect(val).ToNot(BeTrue()) }) It("Uninstalls simple packages not in world correctly", func() { - db := pkg.NewInMemoryDatabase(false) C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - s := NewSolver([]pkg.Package{A, B, C, D}, []pkg.Package{B, C, D}, db) + for _, p := range []pkg.Package{B, C, D} { + _, err := dbDefinitions.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + for _, p := range []pkg.Package{A, B, C, D} { + _, err := dbInstalled.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } solution, err := s.Uninstall(A) Expect(err).ToNot(HaveOccurred()) Expect(solution).To(ContainElement(A.IsFlagged(false))) - // Expect(solution).To(ContainElement(PackageAssert{Package: C.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) + // Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) Expect(len(solution)).To(Equal(1)) }) It("Uninstalls complex packages not in world correctly", func() { - db := pkg.NewInMemoryDatabase(false) - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - s := NewSolver([]pkg.Package{A, B, C, D}, []pkg.Package{B, C, D}, db) + for _, p := range []pkg.Package{B, C, D} { + _, err := dbDefinitions.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + for _, p := range []pkg.Package{A, B, C, D} { + _, err := dbInstalled.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } solution, err := s.Uninstall(A) Expect(err).ToNot(HaveOccurred()) @@ -265,15 +386,20 @@ var _ = Describe("Solver", func() { }) It("Uninstalls complex packages correctly, even if shared deps are required by system packages", func() { - db := pkg.NewInMemoryDatabase(false) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - s := NewSolver([]pkg.Package{A, B, C, D}, []pkg.Package{A, B, C, D}, db) + for _, p := range []pkg.Package{A, B, C, D} { + _, err := dbDefinitions.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + for _, p := range []pkg.Package{A, B, C, D} { + _, err := dbInstalled.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } solution, err := s.Uninstall(A) Expect(err).ToNot(HaveOccurred()) @@ -284,14 +410,20 @@ var _ = Describe("Solver", func() { }) It("Uninstalls complex packages in world correctly", func() { - db := pkg.NewInMemoryDatabase(false) - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{C}, []*pkg.DefaultPackage{}) - s := NewSolver([]pkg.Package{A, C, D}, []pkg.Package{A, B, C, D}, db) + for _, p := range []pkg.Package{A, B, C, D} { + _, err := dbDefinitions.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + + for _, p := range []pkg.Package{A, C, D} { + _, err := dbInstalled.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } solution, err := s.Uninstall(A) Expect(err).ToNot(HaveOccurred()) @@ -303,23 +435,30 @@ var _ = Describe("Solver", func() { }) It("Uninstalls complex package correctly", func() { - db := pkg.NewInMemoryDatabase(false) - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - C.IsFlagged(true) // installed + // C // installed - s := NewSolver([]pkg.Package{A, B, C, D}, []pkg.Package{A, B, C, D}, db) + for _, p := range []pkg.Package{A, B, C, D} { + _, err := dbDefinitions.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + + for _, p := range []pkg.Package{A, B, C, D} { + _, err := dbInstalled.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } solution, err := s.Uninstall(A) + Expect(err).ToNot(HaveOccurred()) + Expect(solution).To(ContainElement(A.IsFlagged(false))) Expect(solution).To(ContainElement(B.IsFlagged(false))) Expect(solution).To(ContainElement(D.IsFlagged(false))) Expect(len(solution)).To(Equal(3)) - Expect(err).ToNot(HaveOccurred()) }) @@ -328,14 +467,20 @@ var _ = Describe("Solver", func() { Context("Conflict set", func() { It("is unsolvable - as we something we ask to install conflict with system stuff", func() { - db := pkg.NewInMemoryDatabase(false) - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) // D := pkg.NewPackage("D", "", []pkg.Package{}, []pkg.Package{}) B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{C}) A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - s := NewSolver([]pkg.Package{C}, []pkg.Package{A, B, C}, db) + for _, p := range []pkg.Package{A, B, C} { + _, err := dbDefinitions.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + + for _, p := range []pkg.Package{C} { + _, err := dbInstalled.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } solution, err := s.Install([]pkg.Package{A}) Expect(len(solution)).To(Equal(0)) @@ -346,8 +491,6 @@ var _ = Describe("Solver", func() { Context("Complex data sets", func() { It("Solves them correctly", func() { - db := pkg.NewInMemoryDatabase(false) - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) E := pkg.NewPackage("E", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) F := pkg.NewPackage("F", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) @@ -357,18 +500,26 @@ var _ = Describe("Solver", func() { B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - s := NewSolver([]pkg.Package{C}, []pkg.Package{A, B, C, D, E, F, G}, db) + for _, p := range []pkg.Package{A, B, C, D, E, F, G} { + _, err := dbDefinitions.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + for _, p := range []pkg.Package{C} { + _, err := dbInstalled.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } solution, err := s.Install([]pkg.Package{A}) - Expect(solution).To(ContainElement(PackageAssert{Package: A.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: B.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: C.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: H.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: G.IsFlagged(true).(*pkg.DefaultPackage), Value: true})) + Expect(err).ToNot(HaveOccurred()) + + Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: H, Value: true})) + Expect(solution).To(ContainElement(PackageAssert{Package: G, Value: true})) Expect(len(solution)).To(Equal(6)) - Expect(err).ToNot(HaveOccurred()) }) }) @@ -391,7 +542,6 @@ var _ = Describe("Solver", func() { Expect(lst).To(ContainElement(a03)) Expect(lst).ToNot(ContainElement(old)) Expect(len(lst)).To(Equal(5)) - s := solver.NewSolver([]pkg.Package{}, []pkg.Package{}, pkg.NewInMemoryDatabase(false)) p := s.Best(lst) Expect(p).To(Equal(a03)) })