Skip to content

Commit

Permalink
Merge pull request #334 from riskpeep/dev-sort-order
Browse files Browse the repository at this point in the history
Added rational sort order for Justifications, Verifications, and Components
  • Loading branch information
shawndwells committed Dec 20, 2018
2 parents 1891cff + c3a7f6b commit f561e7b
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 11 deletions.
6 changes: 5 additions & 1 deletion pkg/lib/common/verifications.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

package common

import (
"vbom.ml/util/sortorder"
)

// Verification struct holds data for a specific component and verification
// This is an internal data structure that helps map standards and controls to components
type Verification struct {
Expand All @@ -21,7 +25,7 @@ func (slice Verifications) Len() int {

// Less returns true if a GeneralReference is less than another reference
func (slice Verifications) Less(i, j int) bool {
return slice[i].ComponentKey < slice[j].ComponentKey
return sortorder.NaturalLess(slice[i].ComponentKey, slice[j].ComponentKey)
}

// Swap swaps the two GeneralReferences
Expand Down
4 changes: 3 additions & 1 deletion pkg/lib/common/verifications_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,16 @@ var verificationsLessTests = []verificationsLessTest{
// Check that the left verification is not less by comparing two numbers
{common.Verifications{common.Verification{ComponentKey: "2", SatisfiesData: nil}, common.Verification{ComponentKey: "1", SatisfiesData: nil}}, false},
// Check that the left verification is not less by comparing two numbers
{common.Verifications{common.Verification{ComponentKey: "2", SatisfiesData: nil}, common.Verification{ComponentKey: "11", SatisfiesData: nil}}, true},
// Check that the left verification is not less by comparing atwo numbers
}

func TestVerificationsLess(t *testing.T) {
for _, example := range verificationsLessTests {
actualLeftIsLess := example.verifications.Less(0, 1)
// Check that the verification on the left is less as expected
if example.leftIsLess != actualLeftIsLess {
t.Errorf("Expected %t, Actual: %t", actualLeftIsLess, actualLeftIsLess)
t.Errorf("Expected %t, Actual: %t", example.leftIsLess, actualLeftIsLess)
}
}
}
15 changes: 15 additions & 0 deletions pkg/lib/components.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"sync"

"fmt"
"sort"
"vbom.ml/util/sortorder"

"github.com/opencontrol/compliance-masonry/pkg/lib/common"
"github.com/opencontrol/compliance-masonry/pkg/lib/components"
Expand All @@ -19,6 +21,18 @@ type componentsMap struct {
sync.RWMutex
}

type byKey []common.Component

func (k byKey) Len() int {
return len(k)
}
func (k byKey) Swap(i, j int) {
k[i], k[j] = k[j], k[i]
}
func (k byKey) Less(i, j int) bool {
return sortorder.NaturalLess(k[i].GetKey(), k[j].GetKey())
}

// newComponents creates an instance of Components struct
func newComponents() *componentsMap {
return &componentsMap{mapping: make(map[string]common.Component)}
Expand Down Expand Up @@ -63,6 +77,7 @@ func (components *componentsMap) getAll() []common.Component {
result[idx] = value
idx++
}
sort.Sort(byKey(result))
return result
}

Expand Down
19 changes: 19 additions & 0 deletions pkg/lib/components_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,25 @@ func TestCompareAndAddComponent(t *testing.T) {
assert.False(t, added)
}

func TestGetAllComponent(t *testing.T) {
m := newComponents()
// Create mock components
newComponent1 := new(mocks.Component)
newComponent1.On("GetKey").Return("11")
m.add(newComponent1)

newComponent2 := new(mocks.Component)
newComponent2.On("GetKey").Return("2")
m.add(newComponent2)

// Try to use getAll to retrieve everything
components := m.getAll()
assert.Equal(t, len(components), 2)

// Check the first return to ensure that we follow natural sort
assert.Equal(t, components[0].GetKey(), "2")
}

func TestLoadSameComponentTwice(t *testing.T) {
ws := localWorkspace{components: newComponents(), justifications: result.NewJustifications()}
componentPath := filepath.Join("..", "..", "test", "fixtures", "component_fixtures", "v3_1_0", "EC2")
Expand Down
18 changes: 9 additions & 9 deletions pkg/lib/opencontrol/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ import (

var _ = Describe("Parse", func() {
var (
parser SchemaParser
err error
openControl common.OpenControl
parser SchemaParser
err error
_ common.OpenControl
)

BeforeEach(func() {
Expand All @@ -30,27 +30,27 @@ var _ = Describe("Parse", func() {
parser = YAMLParser{}
})
It("should detect there's no data to parse when given nil data", func() {
openControl, err = parser.Parse(nil)
_, err = parser.Parse(nil)
assert.Equal(GinkgoT(), common.ErrNoDataToParse, err)
})
It("should detect there's no data to parse when given empty data", func() {
openControl, err = parser.Parse([]byte(""))
_, err = parser.Parse([]byte(""))
assert.Equal(GinkgoT(), common.ErrNoDataToParse, err)
})
It("should detect when it's unable to unmarshal into the base type", func() {
openControl, err = parser.Parse([]byte("schema_version: @"))
_, err = parser.Parse([]byte("schema_version: @"))
assert.Contains(GinkgoT(), err.Error(), ErrMalformedBaseYamlPrefix)
})
It("should detect when it's unable to determine the semver version because it is not in the format", func() {
openControl, err = parser.Parse([]byte("schema_version: versionone"))
_, err = parser.Parse([]byte("schema_version: versionone"))
assert.Equal(GinkgoT(), err, common.ErrCantParseSemver)
})
It("should detect when it's unable to determine the semver version because the version is not in string quotes", func() {
openControl, err = parser.Parse([]byte(`schema_version: 1.0`))
_, err = parser.Parse([]byte(`schema_version: 1.0`))
assert.Equal(GinkgoT(), err, common.ErrCantParseSemver)
})
It("should detect when the version is unknown", func() {
openControl, err = parser.Parse([]byte(`schema_version: "0.0.0"`))
_, err = parser.Parse([]byte(`schema_version: "0.0.0"`))
assert.Equal(GinkgoT(), err, common.ErrUnknownSchemaVersion)
})
})
Expand Down
2 changes: 2 additions & 0 deletions pkg/lib/result/justifications.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package result

import (
"sort"
"sync"

"github.com/opencontrol/compliance-masonry/pkg/lib/common"
Expand Down Expand Up @@ -59,5 +60,6 @@ func (justifications *Justifications) Get(standardKey string, controlKey string)
if !controlKeyExists {
return nil
}
sort.Sort(common.Verifications(controlJustifications))
return controlJustifications
}
27 changes: 27 additions & 0 deletions pkg/lib/result/justifications_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ type justificationsTest struct {
expectedCount int
}

type justificationsOrderTest struct {
mappings []singleMapping
expectedKey string
}

var justificationsAddTests = []justificationsTest{
// Check that justifications can be stored
{[]singleMapping{{"s1", "c", "1"}, {"s2", "c", "2"}, {"s3", "c", "3"}}, 3},
Expand Down Expand Up @@ -59,3 +64,25 @@ func TestJustificationGet(t *testing.T) {
}
}
}

var justificationsGetOrderTests = []justificationsOrderTest{
// Check that the first control returned is 1
{[]singleMapping{{"a", "b", "1"}, {"a", "b", "2"}}, "1"},
// Check that the first control returned is 2
{[]singleMapping{{"a", "b", "11"}, {"a", "b", "2"}}, "2"},
}

func TestJustificationGetOrder(t *testing.T) {
for _, example := range justificationsGetOrderTests {
just := NewJustifications()
for _, mapping := range example.mappings {
just.Add(mapping.standardKey, mapping.controlKey, mapping.componentKey, nil)
}
justs := just.Get("a", "b")

// Check that the first item is the expected item
if justs[0].ComponentKey != example.expectedKey {
t.Errorf("Expected %s, Actual: %s", example.expectedKey, justs[0].ComponentKey)
}
}
}

0 comments on commit f561e7b

Please sign in to comment.