Files
troubleshoot/pkg/analyze/json_compare_test.go
Evans Mungai 1444c01725 feat: json compare host analyser (#1582)
* feat: json compore host analyser

Signed-off-by: Evans Mungai <evans@replicated.com>

* Add missing json compare host analyser file

Signed-off-by: Evans Mungai <evans@replicated.com>

* Generate schemas

Signed-off-by: Evans Mungai <evans@replicated.com>

* Fix failing tests

Signed-off-by: Evans Mungai <evans@replicated.com>

* Ensure json compare analyser always has a title

Signed-off-by: Evans Mungai <evans@replicated.com>

---------

Signed-off-by: Evans Mungai <evans@replicated.com>
2024-07-24 14:27:20 +01:00

821 lines
17 KiB
Go

package analyzer
import (
"testing"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func Test_compareSortedSlices(t *testing.T) {
type args struct {
actual []interface{}
expected []interface{}
}
tests := []struct {
name string
args args
equal bool
}{
{
name: "empty slices",
args: args{
actual: []interface{}{},
expected: []interface{}{},
},
equal: true,
},
{
name: "same order slices",
args: args{
actual: []interface{}{"a", "b", "c"},
expected: []interface{}{"a", "b", "c"},
},
equal: true,
},
{
name: "unordered slices",
args: args{
actual: []interface{}{"a", "b", "c"},
expected: []interface{}{"b", "a", "c"},
},
equal: true,
},
{
name: "different type and unordered slices",
args: args{
actual: []interface{}{1, "a", "c"},
expected: []interface{}{"a", 1, "c"},
},
equal: true,
},
{
name: "unordered slices with map",
args: args{
actual: []interface{}{map[string]int{"a": 1}, "a", "c"},
expected: []interface{}{"a", map[string]int{"a": 1}, "c"},
},
equal: true,
},
{
name: "unequal slices with duplicates",
args: args{
actual: []interface{}{"a", "a", "a", "c"},
expected: []interface{}{"a", "a", "c", "c"},
},
equal: false,
},
{
name: "unordered slices with boolean and strings",
args: args{
actual: []interface{}{true, "a", false, true},
expected: []interface{}{"a", true, false, true},
},
equal: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := compareSortedSlices(tt.args.actual, tt.args.expected)
assert.Equalf(t, tt.equal, got, "compareSlices() = %v, want %v", got, tt.equal)
})
}
}
func Test_jsonCompare(t *testing.T) {
tests := []struct {
name string
isError bool
analyzer troubleshootv1beta2.JsonCompare
expectResult AnalyzeResult
fileContents []byte
}{
{
name: "basic comparison",
analyzer: troubleshootv1beta2.JsonCompare{
Outcomes: []*troubleshootv1beta2.Outcome{
{
Pass: &troubleshootv1beta2.SingleOutcome{
Message: "pass",
},
},
{
Fail: &troubleshootv1beta2.SingleOutcome{
Message: "fail",
},
},
},
CollectorName: "json-compare-1",
FileName: "json-compare-1.json",
Value: `{
"foo": "bar",
"stuff": {
"foo": "bar",
"bar": true
},
"morestuff": [
{
"foo": {
"bar": 123
}
}
]
}`,
},
expectResult: AnalyzeResult{
IsPass: true,
IsWarn: false,
IsFail: false,
Title: "json-compare-1",
Message: "pass",
IconKey: "kubernetes_text_analyze",
IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg",
},
fileContents: []byte(`{
"foo": "bar",
"stuff": {
"foo": "bar",
"bar": true
},
"morestuff": [
{
"foo": {
"bar": 123
}
}
]
}`),
},
{
name: "basic comparison, but fail on match",
analyzer: troubleshootv1beta2.JsonCompare{
Outcomes: []*troubleshootv1beta2.Outcome{
{
Pass: &troubleshootv1beta2.SingleOutcome{
Message: "pass",
When: "false",
},
},
{
Fail: &troubleshootv1beta2.SingleOutcome{
Message: "fail",
When: "true",
},
},
},
CollectorName: "json-compare-1-1",
FileName: "json-compare-1-1.json",
Value: `{
"foo": "bar",
"stuff": {
"foo": "bar",
"bar": true
},
"morestuff": [
{
"foo": {
"bar": 123
}
}
]
}`,
},
expectResult: AnalyzeResult{
IsPass: false,
IsWarn: false,
IsFail: true,
Title: "json-compare-1-1",
Message: "fail",
IconKey: "kubernetes_text_analyze",
IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg",
},
fileContents: []byte(`{
"foo": "bar",
"stuff": {
"foo": "bar",
"bar": true
},
"morestuff": [
{
"foo": {
"bar": 123
}
}
]
}`),
},
{
name: "comparison using path 1",
analyzer: troubleshootv1beta2.JsonCompare{
Outcomes: []*troubleshootv1beta2.Outcome{
{
Pass: &troubleshootv1beta2.SingleOutcome{
Message: "pass",
},
},
{
Fail: &troubleshootv1beta2.SingleOutcome{
Message: "fail",
},
},
},
CollectorName: "json-compare-2",
FileName: "json-compare-2.json",
Path: "morestuff",
Value: `[
{
"foo": {
"bar": 123
}
}
]`,
},
expectResult: AnalyzeResult{
IsPass: true,
IsWarn: false,
IsFail: false,
Title: "json-compare-2",
Message: "pass",
IconKey: "kubernetes_text_analyze",
IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg",
},
fileContents: []byte(`{
"foo": "bar",
"stuff": {
"foo": "bar",
"bar": true
},
"morestuff": [
{
"foo": {
"bar": 123
}
}
]
}`),
},
{
name: "comparison using path 2",
analyzer: troubleshootv1beta2.JsonCompare{
Outcomes: []*troubleshootv1beta2.Outcome{
{
Pass: &troubleshootv1beta2.SingleOutcome{
Message: "pass",
},
},
{
Fail: &troubleshootv1beta2.SingleOutcome{
Message: "fail",
},
},
},
CollectorName: "json-compare-3",
FileName: "json-compare-3.json",
Path: "morestuff.[0].foo.bar",
Value: `123`,
},
expectResult: AnalyzeResult{
IsPass: true,
IsWarn: false,
IsFail: false,
Title: "json-compare-3",
Message: "pass",
IconKey: "kubernetes_text_analyze",
IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg",
},
fileContents: []byte(`{
"foo": "bar",
"stuff": {
"foo": "bar",
"bar": true
},
"morestuff": [
{
"foo": {
"bar": 123
}
}
]
}`),
},
{
name: "comparison using path 2, but warn on match",
analyzer: troubleshootv1beta2.JsonCompare{
Outcomes: []*troubleshootv1beta2.Outcome{
{
Pass: &troubleshootv1beta2.SingleOutcome{
Message: "pass",
When: "false",
},
},
{
Warn: &troubleshootv1beta2.SingleOutcome{
Message: "warn",
When: "true",
},
},
},
CollectorName: "json-compare-3-1",
FileName: "json-compare-3-1.json",
Path: "morestuff.[0].foo.bar",
Value: `123`,
},
expectResult: AnalyzeResult{
IsPass: false,
IsWarn: true,
IsFail: false,
Title: "json-compare-3-1",
Message: "warn",
IconKey: "kubernetes_text_analyze",
IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg",
},
fileContents: []byte(`{
"foo": "bar",
"stuff": {
"foo": "bar",
"bar": true
},
"morestuff": [
{
"foo": {
"bar": 123
}
}
]
}`),
},
{
name: "basic comparison fail",
analyzer: troubleshootv1beta2.JsonCompare{
Outcomes: []*troubleshootv1beta2.Outcome{
{
Pass: &troubleshootv1beta2.SingleOutcome{
Message: "pass",
},
},
{
Fail: &troubleshootv1beta2.SingleOutcome{
Message: "fail",
},
},
},
CollectorName: "json-compare-4",
FileName: "json-compare-4.json",
Value: `{
"foo": "bar",
"stuff": {
"foo": "bar",
"bar": true
},
"morestuff": [
{
"foo": {
"bar": 123
}
}
]
}`,
},
expectResult: AnalyzeResult{
IsPass: false,
IsWarn: false,
IsFail: true,
Title: "json-compare-4",
Message: "fail",
IconKey: "kubernetes_text_analyze",
IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg",
},
fileContents: []byte(`{
"foo": "bar",
"stuff": {
"foo": "bar",
"bar": true
},
"otherstuff": [
{
"foo": {
"bar": 123
}
}
]
}`),
},
{
name: "comparison using path fail 1",
analyzer: troubleshootv1beta2.JsonCompare{
Outcomes: []*troubleshootv1beta2.Outcome{
{
Pass: &troubleshootv1beta2.SingleOutcome{
Message: "pass",
},
},
{
Fail: &troubleshootv1beta2.SingleOutcome{
Message: "fail",
},
},
},
CollectorName: "json-compare-5",
FileName: "json-compare-5.json",
Path: "morestuff",
Value: `[
{
"foo": {
"bar": 321
}
}
]`,
},
expectResult: AnalyzeResult{
IsPass: false,
IsWarn: false,
IsFail: true,
Title: "json-compare-5",
Message: "fail",
IconKey: "kubernetes_text_analyze",
IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg",
},
fileContents: []byte(`{
"foo": "bar",
"stuff": {
"foo": "bar",
"bar": true
},
"morestuff": [
{
"foo": {
"bar": 123
}
}
]
}`),
},
{
name: "comparison using path, but pass when not matching",
analyzer: troubleshootv1beta2.JsonCompare{
Outcomes: []*troubleshootv1beta2.Outcome{
{
Pass: &troubleshootv1beta2.SingleOutcome{
Message: "pass",
When: "false",
},
},
{
Fail: &troubleshootv1beta2.SingleOutcome{
Message: "fail",
When: "true",
},
},
},
CollectorName: "json-compare-5-1",
FileName: "json-compare-5-1.json",
Path: "morestuff",
Value: `[
{
"foo": {
"bar": 321
}
}
]`,
},
expectResult: AnalyzeResult{
IsPass: true,
IsWarn: false,
IsFail: false,
Title: "json-compare-5-1",
Message: "pass",
IconKey: "kubernetes_text_analyze",
IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg",
},
fileContents: []byte(`{
"foo": "bar",
"stuff": {
"foo": "bar",
"bar": true
},
"morestuff": [
{
"foo": {
"bar": 123
}
}
]
}`),
},
{
name: "basic comparison warn",
analyzer: troubleshootv1beta2.JsonCompare{
Outcomes: []*troubleshootv1beta2.Outcome{
{
Pass: &troubleshootv1beta2.SingleOutcome{
Message: "pass",
},
},
{
Warn: &troubleshootv1beta2.SingleOutcome{
Message: "warn",
},
},
},
CollectorName: "json-compare-6",
FileName: "json-compare-6.json",
Value: `{
"foo": "bar",
"stuff": {
"foo": "bar",
"bar": true
},
"morestuff": [
{
"foo": {
"bar": 123
}
}
]
}`,
},
expectResult: AnalyzeResult{
IsPass: false,
IsWarn: true,
IsFail: false,
Title: "json-compare-6",
Message: "warn",
IconKey: "kubernetes_text_analyze",
IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg",
},
fileContents: []byte(`{
"foo": "bar",
"stuff": {
"foo": "bar",
"bar": true
},
"otherstuff": [
{
"foo": {
"bar": 123
}
}
]
}`),
},
{
name: "invalid json error",
isError: true,
analyzer: troubleshootv1beta2.JsonCompare{
Outcomes: []*troubleshootv1beta2.Outcome{
{
Pass: &troubleshootv1beta2.SingleOutcome{
Message: "pass",
},
},
{
Fail: &troubleshootv1beta2.SingleOutcome{
Message: "fail",
},
},
},
CollectorName: "json-compare-7",
FileName: "json-compare-7.json",
Path: "morestuff",
Value: `[
{
"foo": {
"bar": 123
}
}
]`,
},
fileContents: []byte(`{ "this: - is-invalid: json }`),
},
{
name: "no json error",
isError: true,
analyzer: troubleshootv1beta2.JsonCompare{
Outcomes: []*troubleshootv1beta2.Outcome{
{
Pass: &troubleshootv1beta2.SingleOutcome{
Message: "pass",
},
},
{
Fail: &troubleshootv1beta2.SingleOutcome{
Message: "fail",
},
},
},
CollectorName: "json-compare-8",
FileName: "json-compare-8.json",
Path: "morestuff",
Value: `[
{
"foo": {
"bar": 123
}
}
]`,
},
fileContents: []byte(``),
},
{
name: "jsonpath comparison",
analyzer: troubleshootv1beta2.JsonCompare{
Outcomes: []*troubleshootv1beta2.Outcome{
{
Pass: &troubleshootv1beta2.SingleOutcome{
Message: "pass",
},
},
{
Fail: &troubleshootv1beta2.SingleOutcome{
Message: "fail",
},
},
},
CollectorName: "jsonpath-compare-1",
FileName: "jsonpath-compare-1.json",
JsonPath: "{$.morestuff[0]}",
Value: `{
"foo": {
"bar": 123
}
}`,
},
expectResult: AnalyzeResult{
IsPass: true,
IsWarn: false,
IsFail: false,
Title: "jsonpath-compare-1",
Message: "pass",
IconKey: "kubernetes_text_analyze",
IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg",
},
fileContents: []byte(`{
"foo": "bar",
"stuff": {
"foo": "bar",
"bar": true
},
"morestuff": [
{
"foo": {
"bar": 123
}
}
]
}`),
},
{
name: "jsonpath comparison, but fail on match",
analyzer: troubleshootv1beta2.JsonCompare{
Outcomes: []*troubleshootv1beta2.Outcome{
{
Pass: &troubleshootv1beta2.SingleOutcome{
Message: "pass",
When: "false",
},
},
{
Fail: &troubleshootv1beta2.SingleOutcome{
Message: "fail",
When: "true",
},
},
},
CollectorName: "jsonpath-compare-1-1",
FileName: "jsonpath-compare-1-1.json",
JsonPath: "{$.morestuff[0].foo.bar}",
Value: `123`,
},
expectResult: AnalyzeResult{
IsPass: false,
IsWarn: false,
IsFail: true,
Title: "jsonpath-compare-1-1",
Message: "fail",
IconKey: "kubernetes_text_analyze",
IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg",
},
fileContents: []byte(`{
"foo": "bar",
"stuff": {
"foo": "bar",
"bar": true
},
"morestuff": [
{
"foo": {
"bar": 123
}
}
]
}`),
},
{
name: "jsonpath comparison, multiple values",
analyzer: troubleshootv1beta2.JsonCompare{
Outcomes: []*troubleshootv1beta2.Outcome{
{
Pass: &troubleshootv1beta2.SingleOutcome{
Message: "pass",
},
},
{
Fail: &troubleshootv1beta2.SingleOutcome{
Message: "fail",
},
},
},
CollectorName: "jsonpath-compare-2",
FileName: "jsonpath-compare-2.json",
JsonPath: "{$..bar}",
Value: `[true, 123]`,
},
expectResult: AnalyzeResult{
IsPass: true,
IsWarn: false,
IsFail: false,
Title: "jsonpath-compare-2",
Message: "pass",
IconKey: "kubernetes_text_analyze",
IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg",
},
fileContents: []byte(`{
"foo": "bar",
"stuff": {
"foo": "bar",
"bar": true
},
"morestuff": [
{
"foo": {
"bar": 123
}
}
]
}`),
},
{
name: "basic comparison with outcome message templated",
analyzer: troubleshootv1beta2.JsonCompare{
Outcomes: []*troubleshootv1beta2.Outcome{
{
Pass: &troubleshootv1beta2.SingleOutcome{
Message: "Status: {{ .morestuff.status }}, Info: {{ .morestuff.info }}",
When: "true",
},
},
{
Fail: &troubleshootv1beta2.SingleOutcome{
Message: "Status: {{ .morestuff.status }}, Info: {{ .morestuff.info }}",
When: "false",
},
},
},
CollectorName: "json-compare",
FileName: "json-compare.json",
Path: "morestuff.status",
Value: `"ready"`,
},
expectResult: AnalyzeResult{
IsPass: false,
IsWarn: false,
IsFail: true,
Title: "json-compare",
Message: "Status: notready, Info: morestuff is not ready",
IconKey: "kubernetes_text_analyze",
IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg",
},
fileContents: []byte(`{
"stuff": {
"status": "ready",
"info": "this stuff is ready"
},
"morestuff": {
"status": "notready",
"info": "morestuff is not ready"
}
}`),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
req := require.New(t)
getCollectedFileContents := func(n string) ([]byte, error) {
return test.fileContents, nil
}
actual, err := analyzeJsonCompare(&test.analyzer, getCollectedFileContents, test.analyzer.CollectorName)
if !test.isError {
req.NoError(err)
req.Equal(test.expectResult, *actual)
} else {
req.Error(err)
}
})
}
}