1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
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))
})
}
}
|