Skip to content

Commit

Permalink
test: add fuzz test for configloader
Browse files Browse the repository at this point in the history
That PR contains an example of how fuzz tests can be written with Go 1.18.

It also fixes a few panics with invalid configs.

Signed-off-by: Alexey Palazhchenko <alexey.palazhchenko@talos-systems.com>
  • Loading branch information
AlekSi committed Sep 27, 2021
1 parent d2cf021 commit 95f440e
Show file tree
Hide file tree
Showing 8 changed files with 836 additions and 28 deletions.
37 changes: 37 additions & 0 deletions pkg/machinery/config/configloader/configloader_fuzz_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

//go:build go1.18
// +build go1.18

package configloader_test

import (
"os"
"path/filepath"
"testing"

"github.com/stretchr/testify/require"
)

func FuzzConfigLoader(f *testing.F) {
files, err := filepath.Glob(filepath.Join("testdata", "*.test"))
require.NoError(f, err)

for _, file := range files {
b, err := os.ReadFile(file)
require.NoError(f, err)
f.Add(b)
}

f.Add([]byte(": \xea"))
f.Add([]byte(nil))
f.Add([]byte(""))

f.Fuzz(func(t *testing.T, b []byte) {
t.Parallel()

testConfigLoaderBytes(t, b)
})
}
108 changes: 81 additions & 27 deletions pkg/machinery/config/configloader/configloader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,96 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

//nolint:testpackage
package configloader
package configloader_test

import (
"os"
"path/filepath"
"reflect"
"testing"

"github.com/stretchr/testify/suite"
"github.com/stretchr/testify/require"

"github.com/talos-systems/talos/pkg/machinery/config/configloader"
)

// docgen: nodoc
type Suite struct {
suite.Suite
// callMethods calls obj's "getter" methods recursively and fails on panic.
func callMethods(t testing.TB, obj reflect.Value, chain ...string) {
t.Helper()

typ := obj.Type()

for i := 0; i < obj.NumMethod(); i++ {
method := obj.Method(i)

if method.Type().NumIn() != 0 {
continue
}

methodName := typ.Method(i).Name
nextChain := make([]string, len(chain)+1)
copy(nextChain, chain)
nextChain[len(nextChain)-1] = methodName
// t.Log(nextChain)

// skip known broken methods
switch methodName {
case "GetRSAKey", "GetEd25519Key", "GetECDSAKey", "GetCert", "GetKey":
fallthrough
case "MarshalYAML":
fallthrough
case "Endpoint":
// t.Logf("Skipping %v", nextChain)
continue
}

var resS []reflect.Value

require.NotPanics(t, func() { resS = method.Call(nil) }, "Method chain: %v", nextChain)

if len(resS) == 0 {
continue
}

res := resS[0]

// skip result if it has the same type
// to avoid infinite recursion on methods like DeepCopy
if res.Type() == typ {
continue
}

callMethods(t, res, nextChain...)
}
}

func TestSuite(t *testing.T) {
suite.Run(t, new(Suite))
func testConfigLoaderBytes(t testing.TB, b []byte) {
t.Helper()

p, err := configloader.NewFromBytes(b)
if err != nil {
t.Skipf("Failed to load, skipping: %s.", err)
}

callMethods(t, reflect.ValueOf(p))
}

func (suite *Suite) SetupSuite() {}

func (suite *Suite) TestNew() {
for _, tt := range []struct {
source []byte
expectedErr string
}{
{
source: []byte(": \xea"),
expectedErr: "recovered: internal error: attempted to parse unknown event (please report): none",
},
} {
_, err := newConfig(tt.source)

if tt.expectedErr == "" {
suite.Require().NoError(err)
} else {
suite.Require().EqualError(err, tt.expectedErr)
}
// TODO(aleksi): maybe remove once Go 1.18 is out; see https://github.com/golang/go/issues/47413
func TestConfigLoader(t *testing.T) {
t.Parallel()

files, err := filepath.Glob(filepath.Join("testdata", "*.test"))
require.NoError(t, err)

for _, file := range files {
file := file
t.Run(file, func(t *testing.T) {
t.Parallel()

b, err := os.ReadFile(file)
require.NoError(t, err)

testConfigLoaderBytes(t, b)
})
}
}

0 comments on commit 95f440e

Please sign in to comment.