| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- 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))
- })
- }
- }
|