diff --git a/Makefile b/Makefile index 3e163cde..db2bf4a0 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,11 @@ clean: # Clean up artifacts of the development environment to allow for untainte go clean -i -race $(PACKAGE) .PHONY: clean +editor: # Open our default IDE with the project's configuration. + @# WORKAROUND VS.code does not call Delve with absolute paths to files which it needs to set breakpoints. Until either Delve or VS.code have a fix we need to disable "-trimpath" which converts absolute to relative paths of Go builds which is a requirement for reproducible builds. + GOFLAGS="$(GOFLAGS) -trimpath=false" $(ROOT_DIR)/scripts/editor.sh +.PHONY: editor + help: # Show this help message. @grep -E '^[a-zA-Z-][a-zA-Z0-9.-]*?:.*?# (.+)' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?# "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' .PHONY: help diff --git a/evaluate/metrics/assessment.go b/evaluate/metrics/assessment.go index f951345c..4257f87e 100644 --- a/evaluate/metrics/assessment.go +++ b/evaluate/metrics/assessment.go @@ -24,26 +24,30 @@ var ( AssessmentKeyNoExcessResponse = RegisterAssessmentKey("no-excess-response") ) -// Assessments holds numerical assessment metrics. +// Assessments holds a collection of numerical assessment metrics. type Assessments map[AssessmentKey]uint -// Merge combines two assessments into a new assessment and returns it. -func (a Assessments) Merge(o Assessments) Assessments { - if a == nil { - a = Assessments{} - } - if o == nil { - o = Assessments{} - } +// NewAssessments create a new assessment collection. +func NewAssessments() Assessments { + return map[AssessmentKey]uint{} +} - assessments := map[AssessmentKey]uint{} +// Add adds the given assessment collection to the current one. +func (a Assessments) Add(x Assessments) { + for k, v := range x { + a[k] += v + } +} - for _, k := range allAssessmentKeys { - assessments[k] = a[k] +// Merge combines two assessment collections into a new assessment collection and returns the new assessment collection. +func Merge(a Assessments, b Assessments) (c Assessments) { + c = NewAssessments() + if a != nil { + c.Add(a) } - for _, k := range allAssessmentKeys { - assessments[k] = o[k] + if b != nil { + c.Add(b) } - return Assessments(assessments) + return c } diff --git a/evaluate/metrics/assessment_test.go b/evaluate/metrics/assessment_test.go new file mode 100644 index 00000000..5677d09b --- /dev/null +++ b/evaluate/metrics/assessment_test.go @@ -0,0 +1,116 @@ +package metrics + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestAssessmentsAdd(t *testing.T) { + type testCase struct { + Name string + + Assessments Assessments + X Assessments + + ExpectedAssessments Assessments + } + + validate := func(t *testing.T, tc *testCase) { + t.Run(tc.Name, func(t *testing.T) { + tc.Assessments.Add(tc.X) + + assert.Equal(t, tc.Assessments, tc.ExpectedAssessments) + }) + } + + validate(t, &testCase{ + Name: "Empty", + + Assessments: NewAssessments(), + X: NewAssessments(), + + ExpectedAssessments: NewAssessments(), + }) + + validate(t, &testCase{ + Name: "Non existing key", + + Assessments: NewAssessments(), + X: map[AssessmentKey]uint{ + AssessmentKeyNoExcessResponse: 1, + }, + + ExpectedAssessments: map[AssessmentKey]uint{ + AssessmentKeyNoExcessResponse: 1, + }, + }) + + validate(t, &testCase{ + Name: "Existing key", + + Assessments: map[AssessmentKey]uint{ + AssessmentKeyNoExcessResponse: 1, + }, + X: map[AssessmentKey]uint{ + AssessmentKeyNoExcessResponse: 1, + }, + + ExpectedAssessments: map[AssessmentKey]uint{ + AssessmentKeyNoExcessResponse: 2, + }, + }) +} + +func TestMerge(t *testing.T) { + type testCase struct { + Name string + + A Assessments + B Assessments + + ExpectedC Assessments + } + + validate := func(t *testing.T, tc *testCase) { + t.Run(tc.Name, func(t *testing.T) { + actualC := Merge(tc.A, tc.B) + + assert.Equal(t, tc.ExpectedC, actualC) + }) + } + + validate(t, &testCase{ + Name: "Empty", + + ExpectedC: NewAssessments(), + }) + + validate(t, &testCase{ + Name: "Non existing key", + + A: NewAssessments(), + B: map[AssessmentKey]uint{ + AssessmentKeyNoExcessResponse: 1, + }, + + ExpectedC: map[AssessmentKey]uint{ + AssessmentKeyNoExcessResponse: 1, + }, + }) + + validate(t, &testCase{ + Name: "Existing key", + + A: map[AssessmentKey]uint{ + AssessmentKeyNoExcessResponse: 1, + }, + B: map[AssessmentKey]uint{ + AssessmentKeyNoExcessResponse: 1, + }, + + ExpectedC: map[AssessmentKey]uint{ + AssessmentKeyNoExcessResponse: 2, + }, + }) +} diff --git a/evaluate/metrics/metrics.go b/evaluate/metrics/metrics.go index 3967bc06..1ae422c8 100644 --- a/evaluate/metrics/metrics.go +++ b/evaluate/metrics/metrics.go @@ -38,7 +38,7 @@ func (m Metrics) Add(o Metrics) Metrics { Coverage: append(m.Coverage, o.Coverage...), - Assessments: m.Assessments.Merge(o.Assessments), + Assessments: Merge(m.Assessments, o.Assessments), } } diff --git a/evaluate/repository.go b/evaluate/repository.go index db5acc7b..ba564912 100644 --- a/evaluate/repository.go +++ b/evaluate/repository.go @@ -53,7 +53,7 @@ func EvaluateRepository(model model.Model, language language.Language, repositor continue } - metrics.Assessments = metrics.Assessments.Merge(assessments) + metrics.Assessments.Add(assessments) coverage, err := language.Execute(temporaryRepositoryPath) if err != nil { diff --git a/scripts/editor.sh b/scripts/editor.sh new file mode 100755 index 00000000..4de80b88 --- /dev/null +++ b/scripts/editor.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +set -exuo pipefail + +export VSCODE_OPTIONS=${VSCODE_OPTIONS:-""} + +code $VSCODE_OPTIONS $ROOT_DIR