164 lines
3.6 KiB
Go
164 lines
3.6 KiB
Go
package detect
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"io"
|
|
"strings"
|
|
"testing"
|
|
"testing/iotest"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/zricethezav/gitleaks/v8/report"
|
|
)
|
|
|
|
const secret = "AKIAIRYLJVKMPEGZMPJS"
|
|
|
|
type mockReader struct {
|
|
data []byte
|
|
read bool
|
|
|
|
errToReturn error
|
|
}
|
|
|
|
func (r *mockReader) Read(p []byte) (n int, err error) {
|
|
if r.read {
|
|
return 0, io.EOF
|
|
}
|
|
|
|
// Copy data to the provided buffer.
|
|
n = copy(p, r.data)
|
|
r.read = true
|
|
if r.errToReturn != nil {
|
|
return n, r.errToReturn
|
|
}
|
|
|
|
// Return io.EOF along with the bytes.
|
|
return n, io.EOF
|
|
}
|
|
|
|
// TestDetectReader tests the DetectReader function.
|
|
func TestDetectReader(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
reader io.Reader
|
|
bufSize int
|
|
findingsCount int
|
|
}{
|
|
{
|
|
name: "Test case - Reader returns n > 0 bytes and nil error",
|
|
bufSize: 10,
|
|
findingsCount: 1,
|
|
reader: strings.NewReader(secret),
|
|
},
|
|
{
|
|
name: "Test case - Reader returns n > 0 bytes and io.EOF error",
|
|
bufSize: 10,
|
|
findingsCount: 1,
|
|
reader: &mockReader{
|
|
data: []byte(secret),
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
detector, err := NewDetectorDefaultConfig()
|
|
require.NoError(t, err)
|
|
|
|
findings, err := detector.DetectReader(test.reader, test.bufSize)
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, test.findingsCount, len(findings))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestStreamDetectReader(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
reader io.Reader
|
|
bufSize int
|
|
expectedCount int
|
|
expectError bool
|
|
}{
|
|
{
|
|
name: "Single secret streaming",
|
|
bufSize: 10,
|
|
expectedCount: 1,
|
|
reader: strings.NewReader(secret),
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "Empty reader",
|
|
bufSize: 10,
|
|
expectedCount: 0,
|
|
reader: strings.NewReader(""),
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "Reader returns error",
|
|
bufSize: 10,
|
|
expectedCount: 0,
|
|
reader: iotest.ErrReader(errors.New("simulated read error")),
|
|
expectError: true,
|
|
},
|
|
{
|
|
name: "Multiple secrets with larger buffer",
|
|
bufSize: 20,
|
|
expectedCount: 2,
|
|
reader: strings.NewReader(secret + "\n" + secret),
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "Mock reader with EOF",
|
|
bufSize: 10,
|
|
expectedCount: 1,
|
|
reader: &mockReader{data: []byte(secret)},
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "Secret split across boundary",
|
|
bufSize: 1, // 1KB buffer forces multiple reads
|
|
expectedCount: 1,
|
|
reader: io.MultiReader(
|
|
strings.NewReader(secret[:len(secret)/2]),
|
|
strings.NewReader(secret[len(secret)/2:])),
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "Reader returns error after first read",
|
|
bufSize: 1,
|
|
expectedCount: 0,
|
|
reader: &mockReader{
|
|
data: append(bytes.Repeat([]byte("blah"), 1000), []byte(secret)...),
|
|
errToReturn: errors.New("simulated read error"),
|
|
},
|
|
expectError: true,
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
detector, err := NewDetectorDefaultConfig()
|
|
require.NoError(t, err)
|
|
|
|
findingsCh, errCh := detector.StreamDetectReader(test.reader, test.bufSize)
|
|
var findings []report.Finding
|
|
for f := range findingsCh {
|
|
findings = append(findings, f)
|
|
}
|
|
finalErr := <-errCh
|
|
|
|
if test.expectError {
|
|
require.Error(t, finalErr)
|
|
} else {
|
|
require.NoError(t, finalErr)
|
|
}
|
|
|
|
assert.Equal(t, test.expectedCount, len(findings))
|
|
})
|
|
}
|
|
}
|