From 509845b0f61e8cd1506034945c6eb732f99e5f5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenz=20K=C3=A4stle?= Date: Mon, 5 Jun 2023 12:20:14 +0200 Subject: [PATCH 1/2] Add additional test for derived result logic --- result/overall_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/result/overall_test.go b/result/overall_test.go index 403a2a0..3a55186 100644 --- a/result/overall_test.go +++ b/result/overall_test.go @@ -205,6 +205,8 @@ func TestOverall_withEnhancedSubchecks(t *testing.T) { |pd_test=5s pd_test2=1099511627776kB;@3.14:7036874417766;549755813887:1208925819614629174706176;;18446744073709551615 kl;jr2if;l2rkjasdf=5m asdf=18446744073709551615B ` assert.Equal(t, expectedString, resString) + + assert.Equal(t, check.Warning, overall.GetStatus()) } func TestOverall_withSubchecks_Simple_Output(t *testing.T) { From d0679d655e1049d313b1b307ab72da3a67b06f73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenz=20K=C3=A4stle?= Date: Mon, 5 Jun 2023 13:55:31 +0200 Subject: [PATCH 2/2] Hide state attribute to allow sane handling from API This commit hides the "state" attribute of partial results and implements a Setter for it. This way it can remember if the state was set explicitely or not. In combination with the default state, it is now possible to set a default state which is used, if NO partial results and NO explicit states are set later. An example: var subcheck PartialResult subcheck.SetDefaultState(check.Warning) will create a PartialResult which returns Warning if nothing else happens. If I now, later in the code either add PartialResults or set the state explicitely, this is overriden. This way application code does not need to remember in what state it put a PartialResult previously, but can just set a sane default at the beginning. --- result/overall.go | 82 ++++++++++++++++++++++++++------------- result/overall_test.go | 87 +++++++++++++++++++++++++++++++----------- 2 files changed, 119 insertions(+), 50 deletions(-) diff --git a/result/overall.go b/result/overall.go index b065b23..b740a21 100644 --- a/result/overall.go +++ b/result/overall.go @@ -2,6 +2,7 @@ package result import ( + "errors" "fmt" "strings" @@ -24,19 +25,21 @@ type Overall struct { Summary string stateSetExplicitely bool Outputs []string // Deprecate this in a future version - partialResults []PartialResult + PartialResults []PartialResult } type PartialResult struct { - State int + state int // Result state, either set explicitely or derived from partialResults Output string stateSetExplicitely bool // nolint: unused + defaultState int // Default result state, if no partial results are available and no state is set explicitely + defaultStateSet bool // nolint: unused Perfdata perfdata.PerfdataList - partialResults []PartialResult + PartialResults []PartialResult } func (s *PartialResult) String() string { - return fmt.Sprintf("[%s] %s", check.StatusText(s.State), s.Output) + return fmt.Sprintf("[%s] %s", check.StatusText(s.state), s.Output) } // Deprecated: Will be removed in a future version, use Add() instead @@ -80,11 +83,11 @@ func (o *Overall) Add(state int, output string) { } func (o *Overall) AddSubcheck(subcheck PartialResult) { - o.partialResults = append(o.partialResults, subcheck) + o.PartialResults = append(o.PartialResults, subcheck) } func (o *PartialResult) AddSubcheck(subcheck PartialResult) { - o.partialResults = append(o.partialResults, subcheck) + o.PartialResults = append(o.PartialResults, subcheck) } func (o *Overall) GetStatus() int { @@ -101,9 +104,8 @@ func (o *Overall) GetStatus() int { return check.Unknown } } else { - // state set explicitely! - - if len(o.partialResults) == 0 { + // state not set explicitely! + if len(o.PartialResults) == 0 { return check.Unknown } @@ -114,8 +116,8 @@ func (o *Overall) GetStatus() int { unknowns int ) - for _, sc := range o.partialResults { - switch sc.State { + for _, sc := range o.PartialResults { + switch sc.getState() { case check.Critical: criticals++ case check.Warning: @@ -180,7 +182,7 @@ func (o *Overall) GetSummary() string { if !o.stateSetExplicitely { // No, so lets combine the partial ones - if len(o.partialResults) == 0 { + if len(o.PartialResults) == 0 { // Oh, we actually don't have those either o.Summary = "No status information" return o.Summary @@ -193,8 +195,8 @@ func (o *Overall) GetSummary() string { unknowns int ) - for _, sc := range o.partialResults { - switch sc.State { + for _, sc := range o.PartialResults { + switch sc.state { case check.Critical: criticals++ case check.Warning: @@ -237,13 +239,13 @@ func (o *Overall) GetOutput() string { output.WriteString(extra + "\n") } - if o.partialResults != nil { + if o.PartialResults != nil { var pdata strings.Builder // Generate indeted output and perfdata for all partialResults - for i := range o.partialResults { - output.WriteString(o.partialResults[i].getOutput(0)) - pdata.WriteString(" " + o.partialResults[i].getPerfdata()) + for i := range o.PartialResults { + output.WriteString(o.PartialResults[i].getOutput(0)) + pdata.WriteString(" " + o.PartialResults[i].getPerfdata()) } pdata_string := strings.Trim(pdata.String(), " ") @@ -264,8 +266,8 @@ func (s *PartialResult) getPerfdata() string { output.WriteString(s.Perfdata.String()) } - if s.partialResults != nil { - for _, ss := range s.partialResults { + if s.PartialResults != nil { + for _, ss := range s.PartialResults { output.WriteString(ss.getPerfdata()) } } @@ -280,8 +282,8 @@ func (s *PartialResult) getOutput(indent_level int) string { prefix := strings.Repeat(" ", indent_level) output.WriteString(prefix + "\\_ " + s.String() + "\n") - if s.partialResults != nil { - for _, ss := range s.partialResults { + if s.PartialResults != nil { + for _, ss := range s.PartialResults { output.WriteString(ss.getOutput(indent_level + 2)) } } @@ -289,20 +291,46 @@ func (s *PartialResult) getOutput(indent_level int) string { return output.String() } +func (s *PartialResult) SetDefaultState(state int) error { + if state < check.OK || state > check.Unknown { + return errors.New("Default State is not a valid result state. Got " + fmt.Sprint(state) + " which is not valid") + } + + s.defaultState = state + s.defaultStateSet = true + + return nil +} + +func (s *PartialResult) SetState(state int) error { + if state < check.OK || state > check.Unknown { + return errors.New("Default State is not a valid result state. Got " + fmt.Sprint(state) + " which is not valid") + } + + s.state = state + s.stateSetExplicitely = true + + return nil +} + // nolint: unused func (s *PartialResult) getState() int { if s.stateSetExplicitely { - return s.State + return s.state } - if len(s.partialResults) == 0 { + if len(s.PartialResults) == 0 { + if s.defaultStateSet { + return s.defaultState + } + return check.Unknown } - states := make([]int, len(s.partialResults)) + states := make([]int, len(s.PartialResults)) - for i := range s.partialResults { - states[i] = s.partialResults[i].State + for i := range s.PartialResults { + states[i] = s.PartialResults[i].state } return WorstState(states...) diff --git a/result/overall_test.go b/result/overall_test.go index 3a55186..021e9e1 100644 --- a/result/overall_test.go +++ b/result/overall_test.go @@ -112,7 +112,7 @@ func ExampleOverall_Add() { overall.Add(check.Critical, "The other is critical") fmt.Printf("%#v\n", overall) - // Output: result.Overall{oks:1, warnings:0, criticals:1, unknowns:0, Summary:"", stateSetExplicitely:true, Outputs:[]string{"[OK] One element is good", "[CRITICAL] The other is critical"}, partialResults:[]result.PartialResult(nil)} + // Output: result.Overall{oks:1, warnings:0, criticals:1, unknowns:0, Summary:"", stateSetExplicitely:true, Outputs:[]string{"[OK] One element is good", "[CRITICAL] The other is critical"}, PartialResults:[]result.PartialResult(nil)} } func ExampleOverall_GetOutput() { @@ -144,7 +144,7 @@ func ExampleOverall_withSubchecks() { pd_list.Add(&example_perfdata) subcheck := PartialResult{ - State: check.OK, + state: check.OK, Output: "Subcheck1 Test", Perfdata: pd_list, } @@ -184,14 +184,16 @@ func TestOverall_withEnhancedSubchecks(t *testing.T) { pd_list2.Add(&example_perfdata4) subcheck := PartialResult{ - State: check.OK, - Output: "Subcheck1 Test", - Perfdata: pd_list, + state: check.OK, + stateSetExplicitely: true, + Output: "Subcheck1 Test", + Perfdata: pd_list, } subcheck2 := PartialResult{ - State: check.Warning, - Output: "Subcheck2 Test", - Perfdata: pd_list2, + state: check.Warning, + stateSetExplicitely: true, + Output: "Subcheck2 Test", + Perfdata: pd_list2, } overall.AddSubcheck(subcheck) @@ -213,14 +215,14 @@ func TestOverall_withSubchecks_Simple_Output(t *testing.T) { var overall Overall subcheck2 := PartialResult{ - State: check.OK, + state: check.OK, Output: "SubSubcheck", } subcheck := PartialResult{ - State: check.OK, + state: check.OK, Output: "PartialResult", } - subcheck.partialResults = append(subcheck.partialResults, subcheck2) + subcheck.PartialResults = append(subcheck.PartialResults, subcheck2) overall.AddSubcheck(subcheck) @@ -238,11 +240,11 @@ func TestOverall_withSubchecks_Perfdata(t *testing.T) { var overall Overall subcheck2 := PartialResult{ - State: check.OK, + state: check.OK, Output: "SubSubcheck", } subcheck := PartialResult{ - State: check.OK, + state: check.OK, Output: "PartialResult", } @@ -258,7 +260,7 @@ func TestOverall_withSubchecks_Perfdata(t *testing.T) { subcheck2.Perfdata.Add(&perf1) subcheck2.Perfdata.Add(&perf2) - subcheck.partialResults = append(subcheck.partialResults, subcheck2) + subcheck.PartialResults = append(subcheck.PartialResults, subcheck2) overall.AddSubcheck(subcheck) @@ -276,7 +278,7 @@ func TestOverall_withSubchecks_PartialResult(t *testing.T) { var overall Overall subcheck3 := PartialResult{ - State: check.Critical, + state: check.Critical, Output: "SubSubSubcheck", } subcheck2 := PartialResult{ @@ -298,8 +300,8 @@ func TestOverall_withSubchecks_PartialResult(t *testing.T) { subcheck2.Perfdata.Add(&perf1) subcheck2.Perfdata.Add(&perf2) - subcheck2.partialResults = append(subcheck.partialResults, subcheck3) - subcheck.partialResults = append(subcheck.partialResults, subcheck2) + subcheck2.PartialResults = append(subcheck.PartialResults, subcheck3) + subcheck.PartialResults = append(subcheck.PartialResults, subcheck2) overall.AddSubcheck(subcheck) @@ -318,16 +320,19 @@ func TestOverall_withSubchecks_PartialResultStatus(t *testing.T) { var overall Overall subcheck := PartialResult{ - State: check.OK, - Output: "Subcheck", + state: check.OK, + stateSetExplicitely: true, + Output: "Subcheck", } subsubcheck := PartialResult{ - State: check.Warning, - Output: "SubSubcheck", + state: check.Warning, + stateSetExplicitely: true, + Output: "SubSubcheck", } subsubsubcheck := PartialResult{ - State: check.Critical, - Output: "SubSubSubcheck", + state: check.Critical, + stateSetExplicitely: true, + Output: "SubSubSubcheck", } subsubcheck.AddSubcheck(subsubsubcheck) @@ -342,3 +347,39 @@ func TestOverall_withSubchecks_PartialResultStatus(t *testing.T) { assert.Equal(t, res, overall.GetOutput()) assert.Equal(t, 0, overall.GetStatus()) } + +func TestDefaultStates1(t *testing.T) { + var overall Overall + + subcheck := PartialResult{} + + subcheck.SetDefaultState(check.OK) + + overall.AddSubcheck(subcheck) + + assert.Equal(t, check.OK, overall.GetStatus()) +} + +func TestDefaultStates2(t *testing.T) { + var overall Overall + + subcheck := PartialResult{} + + overall.AddSubcheck(subcheck) + + assert.Equal(t, check.Unknown, subcheck.getState()) + assert.Equal(t, check.Unknown, overall.GetStatus()) +} + +func TestDefaultStates3(t *testing.T) { + var overall Overall + + subcheck := PartialResult{} + subcheck.SetDefaultState(check.OK) + + subcheck.SetState(check.Warning) + + overall.AddSubcheck(subcheck) + + assert.Equal(t, check.Warning, overall.GetStatus()) +}