Skip to content
This repository has been archived by the owner on Sep 9, 2020. It is now read-only.

Commit

Permalink
gps/verify: Add LockDiff unit tests
Browse files Browse the repository at this point in the history
These should be nearly comprehensive tests for lock diffing behaviors.
They follow the same functional transform table testing pattern as with
the lock satisfaction tests.
  • Loading branch information
sdboyer committed Jul 9, 2018
1 parent 80eeec7 commit 0db8f69
Show file tree
Hide file tree
Showing 3 changed files with 567 additions and 55 deletions.
41 changes: 41 additions & 0 deletions gps/verify/helper_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,37 @@ func (sl safeLock) Projects() []gps.LockedProject {
return sl.p
}

func (sl safeLock) dup() safeLock {
sl2 := safeLock{
i: make([]string, len(sl.i)),
p: make([]gps.LockedProject, 0, len(sl.p)),
}
copy(sl2.i, sl.i)

for _, lp := range sl.p {
// Only for use with VerifiableProjects.
sl2.p = append(sl2.p, lp.(VerifiableProject).dup())
}

return sl2
}

func (vp VerifiableProject) dup() VerifiableProject {
pkglist := make([]string, len(vp.Packages()))
copy(pkglist, vp.Packages())
hashbytes := make([]byte, len(vp.Digest.Digest))
copy(hashbytes, vp.Digest.Digest)

return VerifiableProject{
LockedProject: gps.NewLockedProject(vp.Ident(), vp.Version(), pkglist),
PruneOpts: vp.PruneOpts,
Digest: VersionedDigest{
HashVersion: vp.Digest.HashVersion,
Digest: hashbytes,
},
}
}

// simpleRootManifest exists so that we have a safe value to swap into solver
// params when a nil Manifest is provided.
type simpleRootManifest struct {
Expand Down Expand Up @@ -76,3 +107,13 @@ func (m simpleRootManifest) dup() simpleRootManifest {

return m2
}

func newVerifiableProject(id gps.ProjectIdentifier, v gps.Version, pkgs []string) VerifiableProject {
return VerifiableProject{
LockedProject: gps.NewLockedProject(id, v, pkgs),
Digest: VersionedDigest{
HashVersion: HashVersion,
Digest: []byte("something"),
},
}
}
98 changes: 43 additions & 55 deletions gps/verify/lockdiff.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

Expand All @@ -12,22 +12,25 @@ import (
"github.com/golang/dep/gps"
)

// sortLockedProjects returns a sorted copy of lps, or itself if already sorted.
func sortLockedProjects(lps []gps.LockedProject) []gps.LockedProject {
if len(lps) <= 1 || sort.SliceIsSorted(lps, func(i, j int) bool {
return lps[i].Ident().Less(lps[j].Ident())
}) {
return lps
}

cp := make([]gps.LockedProject, len(lps))
copy(cp, lps)
// DeltaDimension defines a bitset enumerating all of the different dimensions
// along which a Lock, and its constitutent components, can change.
type DeltaDimension uint32

sort.Slice(cp, func(i, j int) bool {
return cp[i].Ident().Less(cp[j].Ident())
})
return cp
}
// Each flag represents an ortohgonal dimension along which Locks can vary with
// respect to each other.
const (
InputImportsChanged DeltaDimension = 1 << iota
ProjectAdded
ProjectRemoved
SourceChanged
VersionChanged
RevisionChanged
PackagesChanged
PruneOptsChanged
HashVersionChanged
HashChanged
AnyChanged = (1 << iota) - 1
)

// LockDelta represents all possible differences between two Locks.
type LockDelta struct {
Expand Down Expand Up @@ -61,9 +64,10 @@ type LockedProjectPropertiesDelta struct {
// DiffLocks compares two locks and computes a semantically rich delta between
// them.
func DiffLocks(l1, l2 gps.Lock) LockDelta {
// Default nil locks to empty locks, so that we can still generate a diff
// Default nil locks to empty locks, so that we can still generate a diff.
if l1 == nil {
if l2 == nil {
// But both locks being nil results in an empty delta.
return LockDelta{}
}
l1 = gps.SimpleLock{}
Expand Down Expand Up @@ -131,8 +135,8 @@ func DiffLocks(l1, l2 gps.Lock) LockDelta {
}

func findAddedAndRemoved(l1, l2 []string) (add, remove []string) {
// Computing package add/removes could probably be optimized to O(n), but
// it's not critical path for any known case, so not worth the effort right now.
// Computing package add/removes might be optimizable to O(n) (?), but it's
// not critical path for any known case, so not worth the effort right now.
p1, p2 := make(map[string]bool, len(l1)), make(map[string]bool, len(l2))

for _, pkg := range l1 {
Expand Down Expand Up @@ -216,26 +220,6 @@ func DiffLockedProjectProperties(lp1, lp2 gps.LockedProject) LockedProjectProper
return ld
}

// DeltaDimension defines a bitset enumerating all of the different dimensions
// along which a Lock, and its constitutent components, can change.
type DeltaDimension uint32

// Each flag represents an ortohgonal dimension along which Locks can vary with
// respect to each other.
const (
InputImportsChanged DeltaDimension = 1 << iota
ProjectAdded
ProjectRemoved
SourceChanged
VersionChanged
RevisionChanged
PackagesChanged
PruneOptsChanged
HashVersionChanged
HashChanged
AnyChanged = (1 << iota) - 1
)

// Changed indicates whether the delta contains a change along the dimensions
// with their corresponding bits set.
//
Expand Down Expand Up @@ -388,8 +372,9 @@ func (ld LockedProjectPropertiesDelta) SourceChanged() bool {

// VersionChanged returns true if the version property differed between the
// first and second locks. In addition to simple changes (e.g. 1.0.1 -> 1.0.2),
// this also includes all the possible type changes covered by
// VersionTypeCHanged(), as those necessarily also are version changes.
// this also includes all possible version type changes either going from a
// paired version to a plain revision, or the reverse direction, or the type of
// unpaired version changing (e.g. branch -> semver).
func (ld LockedProjectPropertiesDelta) VersionChanged() bool {
if ld.VersionBefore == nil && ld.VersionAfter == nil {
return false
Expand All @@ -402,20 +387,6 @@ func (ld LockedProjectPropertiesDelta) VersionChanged() bool {
return false
}

// VersionTypeChanged returns true if the type of version differed between the
// first and second locks. This includes either going from a paired version to a
// plain revision, or the reverse direction, or the type of unpaired version
// changing (e.g. branch -> semver).
func (ld LockedProjectPropertiesDelta) VersionTypeChanged() bool {
if ld.VersionBefore == nil && ld.VersionAfter == nil {
return false
} else if (ld.VersionBefore == nil || ld.VersionAfter == nil) || (ld.VersionBefore.Type() != ld.VersionAfter.Type()) {
return true
}

return false
}

// RevisionChanged returns true if the revision property differed between the
// first and second locks.
func (ld LockedProjectPropertiesDelta) RevisionChanged() bool {
Expand All @@ -433,3 +404,20 @@ func (ld LockedProjectPropertiesDelta) PackagesChanged() bool {
func (ld LockedProjectPropertiesDelta) PruneOptsChanged() bool {
return ld.PruneOptsBefore != ld.PruneOptsAfter
}

// sortLockedProjects returns a sorted copy of lps, or itself if already sorted.
func sortLockedProjects(lps []gps.LockedProject) []gps.LockedProject {
if len(lps) <= 1 || sort.SliceIsSorted(lps, func(i, j int) bool {
return lps[i].Ident().Less(lps[j].Ident())
}) {
return lps
}

cp := make([]gps.LockedProject, len(lps))
copy(cp, lps)

sort.Slice(cp, func(i, j int) bool {
return cp[i].Ident().Less(cp[j].Ident())
})
return cp
}
Loading

0 comments on commit 0db8f69

Please sign in to comment.