mirror of
https://github.com/kubeshark/kubeshark.git
synced 2026-08-19 04:16:35 +00:00
* deps: bump indirect deps to clear critical/high Dependabot alerts Bumps the vulnerable indirect dependencies flagged as critical or high severity in Dependabot: - golang.org/x/crypto v0.39.0 -> v0.54.0 (7 critical + 2 high: SSH agent constraint/key-constraint bypass, @revoked auth bypass, FIDO/U2F presence check bypass, VerifiedPublicKeyCallback permission skip, infinite loop on large channel writes, client-induced server deadlock, RSA/DSA DoS, byte arithmetic underflow panic) - google.golang.org/grpc v1.68.1 -> v1.83.0 (critical: authz bypass via missing leading slash in :path; high: xDS RBAC and HTTP/2 issues) - github.com/containerd/containerd v1.7.27 -> v1.7.34 (high: LABEL -> restart-monitor binary:// host-root RCE, runAsNonRoot evasion, local privesc via wide CRI directory permissions) - oras.land/oras-go/v2 v2.6.0 -> v2.6.2 (high: CVE-2026-50163 hardlink extract-dir escape, credential forwarding via unvalidated Location header) - github.com/moby/spdystream v0.5.0 -> v0.5.1 (high: DoS on CRI) Transitively pulls up x/net, x/sync, x/sys, x/term, x/text, x/time, x/oauth2, protobuf, filepath-securejoin, selinux and go-logr via go mod tidy. The go directive moves 1.24.0 -> 1.25.0 (required by the upgraded modules); the explicit toolchain pin is dropped. CI resolves Go from go.mod, so no workflow changes are needed. go build ./... and go test ./... pass. * ci: move golangci-lint to v2, fix resulting lint issues golangci-lint-action@v3 pins `latest` to v1.64.8, which is built with go1.24 and refuses to run now that go.mod targets 1.25.0: can't load config: the Go language version (go1.24) used to build golangci-lint is lower than the targeted Go version (1.25.0) Move the job to golangci-lint-action@v7 + v2.8.0 and add a .golangci.yml mirroring the hub repo's v2 config: govet, staticcheck, ineffassign and unused, plus gofmt/goimports as formatters. Fixes for the issues that surfaced: - ST1005: lowercase error strings, drop trailing '!' in connect/hub.go - SA4011: kubernetes/watch.go had a `break` inside a `select` default that broke the select rather than the loop, i.e. a no-op; removed - QF1008: drop the embedded ChartPathOptions selector in helm.go - QF1003: tagged switch on r.URL.Path in mcp_test.go - QF1004: strings.Replace(..., -1) -> strings.ReplaceAll - gofmt -s and goimports with a local prefix across the tree errcheck is not in the enabled set, matching hub. * cmd: clarify --time parse error in pcap dump The error neither named the offending flag/value nor separated the wrapped error from the message. Reported by Copilot on #1952. --------- Co-authored-by: Alon Girmonsky <1990761+alongir@users.noreply.github.com>
386 lines
16 KiB
Go
386 lines
16 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
type ConfigMock struct {
|
|
SectionMock SectionMock `yaml:"section"`
|
|
Test string `yaml:"test"`
|
|
StringField string `yaml:"string-field"`
|
|
IntField int `yaml:"int-field"`
|
|
BoolField bool `yaml:"bool-field"`
|
|
UintField uint `yaml:"uint-field"`
|
|
StringSliceField []string `yaml:"string-slice-field"`
|
|
IntSliceField []int `yaml:"int-slice-field"`
|
|
BoolSliceField []bool `yaml:"bool-slice-field"`
|
|
UintSliceField []uint `yaml:"uint-slice-field"`
|
|
}
|
|
|
|
type SectionMock struct {
|
|
Test string `yaml:"test"`
|
|
}
|
|
|
|
type FieldSetValues struct {
|
|
SetValues []string
|
|
FieldName string
|
|
FieldValue interface{}
|
|
}
|
|
|
|
func TestMergeSetFlagNoSeparator(t *testing.T) {
|
|
tests := []struct {
|
|
Name string
|
|
SetValues []string
|
|
}{
|
|
{Name: "empty value", SetValues: []string{""}},
|
|
{Name: "single char", SetValues: []string{"t"}},
|
|
{Name: "combine empty value and single char", SetValues: []string{"", "t"}},
|
|
{Name: "two values without separator", SetValues: []string{"test", "test:true"}},
|
|
{Name: "four values without separator", SetValues: []string{"test", "test:true", "testing!", "true"}},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.Name, func(t *testing.T) {
|
|
configMock := ConfigMock{}
|
|
configMockElemValue := reflect.ValueOf(&configMock).Elem()
|
|
|
|
err := mergeSetFlag(configMockElemValue, test.SetValues)
|
|
|
|
if err == nil {
|
|
t.Errorf("unexpected unhandled error - SetValues: %v", test.SetValues)
|
|
return
|
|
}
|
|
|
|
for i := 0; i < configMockElemValue.NumField(); i++ {
|
|
currentField := configMockElemValue.Type().Field(i)
|
|
currentFieldByName := configMockElemValue.FieldByName(currentField.Name)
|
|
|
|
if !currentFieldByName.IsZero() {
|
|
t.Errorf("unexpected value with not default value - SetValues: %v", test.SetValues)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMergeSetFlagInvalidFlagName(t *testing.T) {
|
|
tests := []struct {
|
|
Name string
|
|
SetValues []string
|
|
}{
|
|
{Name: "invalid flag name", SetValues: []string{"invalid_flag=true"}},
|
|
{Name: "invalid flag name inside section struct", SetValues: []string{"section.invalid_flag=test"}},
|
|
{Name: "flag name is a struct", SetValues: []string{"section=test"}},
|
|
{Name: "empty flag name", SetValues: []string{"=true"}},
|
|
{Name: "four tests combined", SetValues: []string{"invalid_flag=true", "config.invalid_flag=test", "section=test", "=true"}},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.Name, func(t *testing.T) {
|
|
configMock := ConfigMock{}
|
|
configMockElemValue := reflect.ValueOf(&configMock).Elem()
|
|
|
|
err := mergeSetFlag(configMockElemValue, test.SetValues)
|
|
|
|
if err == nil {
|
|
t.Errorf("unexpected unhandled error - SetValues: %v", test.SetValues)
|
|
return
|
|
}
|
|
|
|
for i := 0; i < configMockElemValue.NumField(); i++ {
|
|
currentField := configMockElemValue.Type().Field(i)
|
|
currentFieldByName := configMockElemValue.FieldByName(currentField.Name)
|
|
|
|
if !currentFieldByName.IsZero() {
|
|
t.Errorf("unexpected case - SetValues: %v", test.SetValues)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMergeSetFlagInvalidFlagValue(t *testing.T) {
|
|
tests := []struct {
|
|
Name string
|
|
SetValues []string
|
|
}{
|
|
{Name: "bool value to int field", SetValues: []string{"int-field=true"}},
|
|
{Name: "int value to bool field", SetValues: []string{"bool-field:5"}},
|
|
{Name: "int value to uint field", SetValues: []string{"uint-field=-1"}},
|
|
{Name: "bool value to int slice field", SetValues: []string{"int-slice-field=true"}},
|
|
{Name: "int value to bool slice field", SetValues: []string{"bool-slice-field=5"}},
|
|
{Name: "int value to uint slice field", SetValues: []string{"uint-slice-field=-1"}},
|
|
{Name: "int slice value to int field", SetValues: []string{"int-field=6", "int-field=66"}},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.Name, func(t *testing.T) {
|
|
configMock := ConfigMock{}
|
|
configMockElemValue := reflect.ValueOf(&configMock).Elem()
|
|
|
|
err := mergeSetFlag(configMockElemValue, test.SetValues)
|
|
|
|
if err == nil {
|
|
t.Errorf("unexpected unhandled error - SetValues: %v", test.SetValues)
|
|
return
|
|
}
|
|
|
|
for i := 0; i < configMockElemValue.NumField(); i++ {
|
|
currentField := configMockElemValue.Type().Field(i)
|
|
currentFieldByName := configMockElemValue.FieldByName(currentField.Name)
|
|
|
|
if !currentFieldByName.IsZero() {
|
|
t.Errorf("unexpected case - SetValues: %v", test.SetValues)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMergeSetFlagNotSliceValues(t *testing.T) {
|
|
tests := []struct {
|
|
Name string
|
|
FieldsSetValues []FieldSetValues
|
|
}{
|
|
{Name: "string field", FieldsSetValues: []FieldSetValues{{SetValues: []string{"string-field=test"}, FieldName: "StringField", FieldValue: "test"}}},
|
|
{Name: "int field", FieldsSetValues: []FieldSetValues{{SetValues: []string{"int-field=6"}, FieldName: "IntField", FieldValue: 6}}},
|
|
{Name: "bool field", FieldsSetValues: []FieldSetValues{{SetValues: []string{"bool-field=true"}, FieldName: "BoolField", FieldValue: true}}},
|
|
{Name: "uint field", FieldsSetValues: []FieldSetValues{{SetValues: []string{"uint-field=6"}, FieldName: "UintField", FieldValue: uint(6)}}},
|
|
{Name: "four fields combined", FieldsSetValues: []FieldSetValues{
|
|
{SetValues: []string{"string-field=test"}, FieldName: "StringField", FieldValue: "test"},
|
|
{SetValues: []string{"int-field=6"}, FieldName: "IntField", FieldValue: 6},
|
|
{SetValues: []string{"bool-field=true"}, FieldName: "BoolField", FieldValue: true},
|
|
{SetValues: []string{"uint-field=6"}, FieldName: "UintField", FieldValue: uint(6)},
|
|
}},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.Name, func(t *testing.T) {
|
|
configMock := ConfigMock{}
|
|
configMockElemValue := reflect.ValueOf(&configMock).Elem()
|
|
|
|
var setValues []string
|
|
for _, fieldSetValues := range test.FieldsSetValues {
|
|
setValues = append(setValues, fieldSetValues.SetValues...)
|
|
}
|
|
|
|
err := mergeSetFlag(configMockElemValue, setValues)
|
|
|
|
if err != nil {
|
|
t.Errorf("unexpected error result - err: %v", err)
|
|
return
|
|
}
|
|
|
|
for _, fieldSetValues := range test.FieldsSetValues {
|
|
fieldValue := configMockElemValue.FieldByName(fieldSetValues.FieldName).Interface()
|
|
if fieldValue != fieldSetValues.FieldValue {
|
|
t.Errorf("unexpected result - expected: %v, actual: %v", fieldSetValues.FieldValue, fieldValue)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMergeSetFlagSliceValues(t *testing.T) {
|
|
tests := []struct {
|
|
Name string
|
|
FieldsSetValues []FieldSetValues
|
|
}{
|
|
{Name: "string slice field single value", FieldsSetValues: []FieldSetValues{{SetValues: []string{"string-slice-field=test"}, FieldName: "StringSliceField", FieldValue: []string{"test"}}}},
|
|
{Name: "int slice field single value", FieldsSetValues: []FieldSetValues{{SetValues: []string{"int-slice-field=6"}, FieldName: "IntSliceField", FieldValue: []int{6}}}},
|
|
{Name: "bool slice field single value", FieldsSetValues: []FieldSetValues{{SetValues: []string{"bool-slice-field=true"}, FieldName: "BoolSliceField", FieldValue: []bool{true}}}},
|
|
{Name: "uint slice field single value", FieldsSetValues: []FieldSetValues{{SetValues: []string{"uint-slice-field=6"}, FieldName: "UintSliceField", FieldValue: []uint{uint(6)}}}},
|
|
{Name: "four single value fields combined", FieldsSetValues: []FieldSetValues{
|
|
{SetValues: []string{"string-slice-field=test"}, FieldName: "StringSliceField", FieldValue: []string{"test"}},
|
|
{SetValues: []string{"int-slice-field=6"}, FieldName: "IntSliceField", FieldValue: []int{6}},
|
|
{SetValues: []string{"bool-slice-field=true"}, FieldName: "BoolSliceField", FieldValue: []bool{true}},
|
|
{SetValues: []string{"uint-slice-field=6"}, FieldName: "UintSliceField", FieldValue: []uint{uint(6)}},
|
|
}},
|
|
{Name: "string slice field two values", FieldsSetValues: []FieldSetValues{{SetValues: []string{"string-slice-field=test", "string-slice-field=test2"}, FieldName: "StringSliceField", FieldValue: []string{"test", "test2"}}}},
|
|
{Name: "int slice field two values", FieldsSetValues: []FieldSetValues{{SetValues: []string{"int-slice-field=6", "int-slice-field=66"}, FieldName: "IntSliceField", FieldValue: []int{6, 66}}}},
|
|
{Name: "bool slice field two values", FieldsSetValues: []FieldSetValues{{SetValues: []string{"bool-slice-field=true", "bool-slice-field=false"}, FieldName: "BoolSliceField", FieldValue: []bool{true, false}}}},
|
|
{Name: "uint slice field two values", FieldsSetValues: []FieldSetValues{{SetValues: []string{"uint-slice-field=6", "uint-slice-field=66"}, FieldName: "UintSliceField", FieldValue: []uint{uint(6), uint(66)}}}},
|
|
{Name: "four two values fields combined", FieldsSetValues: []FieldSetValues{
|
|
{SetValues: []string{"string-slice-field=test", "string-slice-field=test2"}, FieldName: "StringSliceField", FieldValue: []string{"test", "test2"}},
|
|
{SetValues: []string{"int-slice-field=6", "int-slice-field=66"}, FieldName: "IntSliceField", FieldValue: []int{6, 66}},
|
|
{SetValues: []string{"bool-slice-field=true", "bool-slice-field=false"}, FieldName: "BoolSliceField", FieldValue: []bool{true, false}},
|
|
{SetValues: []string{"uint-slice-field=6", "uint-slice-field=66"}, FieldName: "UintSliceField", FieldValue: []uint{uint(6), uint(66)}},
|
|
}},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.Name, func(t *testing.T) {
|
|
configMock := ConfigMock{}
|
|
configMockElemValue := reflect.ValueOf(&configMock).Elem()
|
|
|
|
var setValues []string
|
|
for _, fieldSetValues := range test.FieldsSetValues {
|
|
setValues = append(setValues, fieldSetValues.SetValues...)
|
|
}
|
|
|
|
err := mergeSetFlag(configMockElemValue, setValues)
|
|
|
|
if err != nil {
|
|
t.Errorf("unexpected error result - err: %v", err)
|
|
return
|
|
}
|
|
|
|
for _, fieldSetValues := range test.FieldsSetValues {
|
|
fieldValue := configMockElemValue.FieldByName(fieldSetValues.FieldName).Interface()
|
|
if !reflect.DeepEqual(fieldValue, fieldSetValues.FieldValue) {
|
|
t.Errorf("unexpected result - expected: %v, actual: %v", fieldSetValues.FieldValue, fieldValue)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMergeSetFlagMixValues(t *testing.T) {
|
|
tests := []struct {
|
|
Name string
|
|
FieldsSetValues []FieldSetValues
|
|
}{
|
|
{Name: "single value all fields", FieldsSetValues: []FieldSetValues{
|
|
{SetValues: []string{"string-slice-field=test"}, FieldName: "StringSliceField", FieldValue: []string{"test"}},
|
|
{SetValues: []string{"int-slice-field=6"}, FieldName: "IntSliceField", FieldValue: []int{6}},
|
|
{SetValues: []string{"bool-slice-field=true"}, FieldName: "BoolSliceField", FieldValue: []bool{true}},
|
|
{SetValues: []string{"uint-slice-field=6"}, FieldName: "UintSliceField", FieldValue: []uint{uint(6)}},
|
|
{SetValues: []string{"string-field=test"}, FieldName: "StringField", FieldValue: "test"},
|
|
{SetValues: []string{"int-field=6"}, FieldName: "IntField", FieldValue: 6},
|
|
{SetValues: []string{"bool-field=true"}, FieldName: "BoolField", FieldValue: true},
|
|
{SetValues: []string{"uint-field=6"}, FieldName: "UintField", FieldValue: uint(6)},
|
|
}},
|
|
{Name: "two values slice fields and single value fields", FieldsSetValues: []FieldSetValues{
|
|
{SetValues: []string{"string-slice-field=test", "string-slice-field=test2"}, FieldName: "StringSliceField", FieldValue: []string{"test", "test2"}},
|
|
{SetValues: []string{"int-slice-field=6", "int-slice-field=66"}, FieldName: "IntSliceField", FieldValue: []int{6, 66}},
|
|
{SetValues: []string{"bool-slice-field=true", "bool-slice-field=false"}, FieldName: "BoolSliceField", FieldValue: []bool{true, false}},
|
|
{SetValues: []string{"uint-slice-field=6", "uint-slice-field=66"}, FieldName: "UintSliceField", FieldValue: []uint{uint(6), uint(66)}},
|
|
{SetValues: []string{"string-field=test"}, FieldName: "StringField", FieldValue: "test"},
|
|
{SetValues: []string{"int-field=6"}, FieldName: "IntField", FieldValue: 6},
|
|
{SetValues: []string{"bool-field=true"}, FieldName: "BoolField", FieldValue: true},
|
|
{SetValues: []string{"uint-field=6"}, FieldName: "UintField", FieldValue: uint(6)},
|
|
}},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.Name, func(t *testing.T) {
|
|
configMock := ConfigMock{}
|
|
configMockElemValue := reflect.ValueOf(&configMock).Elem()
|
|
|
|
var setValues []string
|
|
for _, fieldSetValues := range test.FieldsSetValues {
|
|
setValues = append(setValues, fieldSetValues.SetValues...)
|
|
}
|
|
|
|
err := mergeSetFlag(configMockElemValue, setValues)
|
|
|
|
if err != nil {
|
|
t.Errorf("unexpected error result - err: %v", err)
|
|
return
|
|
}
|
|
|
|
for _, fieldSetValues := range test.FieldsSetValues {
|
|
fieldValue := configMockElemValue.FieldByName(fieldSetValues.FieldName).Interface()
|
|
if !reflect.DeepEqual(fieldValue, fieldSetValues.FieldValue) {
|
|
t.Errorf("unexpected result - expected: %v, actual: %v", fieldSetValues.FieldValue, fieldValue)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetParsedValueValidValue(t *testing.T) {
|
|
tests := []struct {
|
|
StringValue string
|
|
Kind reflect.Kind
|
|
ActualValue interface{}
|
|
}{
|
|
{StringValue: "test", Kind: reflect.String, ActualValue: "test"},
|
|
{StringValue: "123", Kind: reflect.String, ActualValue: "123"},
|
|
{StringValue: "true", Kind: reflect.Bool, ActualValue: true},
|
|
{StringValue: "false", Kind: reflect.Bool, ActualValue: false},
|
|
{StringValue: "6", Kind: reflect.Int, ActualValue: 6},
|
|
{StringValue: "-6", Kind: reflect.Int, ActualValue: -6},
|
|
{StringValue: "6", Kind: reflect.Int8, ActualValue: int8(6)},
|
|
{StringValue: "-6", Kind: reflect.Int8, ActualValue: int8(-6)},
|
|
{StringValue: "6", Kind: reflect.Int16, ActualValue: int16(6)},
|
|
{StringValue: "-6", Kind: reflect.Int16, ActualValue: int16(-6)},
|
|
{StringValue: "6", Kind: reflect.Int32, ActualValue: int32(6)},
|
|
{StringValue: "-6", Kind: reflect.Int32, ActualValue: int32(-6)},
|
|
{StringValue: "6", Kind: reflect.Int64, ActualValue: int64(6)},
|
|
{StringValue: "-6", Kind: reflect.Int64, ActualValue: int64(-6)},
|
|
{StringValue: "6", Kind: reflect.Uint, ActualValue: uint(6)},
|
|
{StringValue: "66", Kind: reflect.Uint, ActualValue: uint(66)},
|
|
{StringValue: "6", Kind: reflect.Uint8, ActualValue: uint8(6)},
|
|
{StringValue: "66", Kind: reflect.Uint8, ActualValue: uint8(66)},
|
|
{StringValue: "6", Kind: reflect.Uint16, ActualValue: uint16(6)},
|
|
{StringValue: "66", Kind: reflect.Uint16, ActualValue: uint16(66)},
|
|
{StringValue: "6", Kind: reflect.Uint32, ActualValue: uint32(6)},
|
|
{StringValue: "66", Kind: reflect.Uint32, ActualValue: uint32(66)},
|
|
{StringValue: "6", Kind: reflect.Uint64, ActualValue: uint64(6)},
|
|
{StringValue: "66", Kind: reflect.Uint64, ActualValue: uint64(66)},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(fmt.Sprintf("%v %v", test.Kind, test.StringValue), func(t *testing.T) {
|
|
parsedValue, err := getParsedValue(test.Kind, test.StringValue)
|
|
|
|
if err != nil {
|
|
t.Errorf("unexpected error result - err: %v", err)
|
|
return
|
|
}
|
|
|
|
if parsedValue.Interface() != test.ActualValue {
|
|
t.Errorf("unexpected result - expected: %v, actual: %v", test.ActualValue, parsedValue)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetParsedValueInvalidValue(t *testing.T) {
|
|
tests := []struct {
|
|
StringValue string
|
|
Kind reflect.Kind
|
|
}{
|
|
{StringValue: "test", Kind: reflect.Bool},
|
|
{StringValue: "123", Kind: reflect.Bool},
|
|
{StringValue: "test", Kind: reflect.Int},
|
|
{StringValue: "true", Kind: reflect.Int},
|
|
{StringValue: "test", Kind: reflect.Int8},
|
|
{StringValue: "true", Kind: reflect.Int8},
|
|
{StringValue: "test", Kind: reflect.Int16},
|
|
{StringValue: "true", Kind: reflect.Int16},
|
|
{StringValue: "test", Kind: reflect.Int32},
|
|
{StringValue: "true", Kind: reflect.Int32},
|
|
{StringValue: "test", Kind: reflect.Int64},
|
|
{StringValue: "true", Kind: reflect.Int64},
|
|
{StringValue: "test", Kind: reflect.Uint},
|
|
{StringValue: "-6", Kind: reflect.Uint},
|
|
{StringValue: "test", Kind: reflect.Uint8},
|
|
{StringValue: "-6", Kind: reflect.Uint8},
|
|
{StringValue: "test", Kind: reflect.Uint16},
|
|
{StringValue: "-6", Kind: reflect.Uint16},
|
|
{StringValue: "test", Kind: reflect.Uint32},
|
|
{StringValue: "-6", Kind: reflect.Uint32},
|
|
{StringValue: "test", Kind: reflect.Uint64},
|
|
{StringValue: "-6", Kind: reflect.Uint64},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(fmt.Sprintf("%v %v", test.Kind, test.StringValue), func(t *testing.T) {
|
|
parsedValue, err := getParsedValue(test.Kind, test.StringValue)
|
|
|
|
if err == nil {
|
|
t.Errorf("unexpected unhandled error - stringValue: %v, Kind: %v", test.StringValue, test.Kind)
|
|
return
|
|
}
|
|
|
|
if parsedValue != reflect.ValueOf(nil) {
|
|
t.Errorf("unexpected parsed value - parsedValue: %v", parsedValue)
|
|
}
|
|
})
|
|
}
|
|
}
|