reader_test.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. package detect
  2. import (
  3. "bytes"
  4. "errors"
  5. "io"
  6. "strings"
  7. "testing"
  8. "testing/iotest"
  9. "github.com/stretchr/testify/assert"
  10. "github.com/stretchr/testify/require"
  11. "github.com/zricethezav/gitleaks/v8/report"
  12. )
  13. const secret = "AKIAIRYLJVKMPEGZMPJS"
  14. type mockReader struct {
  15. data []byte
  16. read bool
  17. errToReturn error
  18. }
  19. func (r *mockReader) Read(p []byte) (n int, err error) {
  20. if r.read {
  21. return 0, io.EOF
  22. }
  23. // Copy data to the provided buffer.
  24. n = copy(p, r.data)
  25. r.read = true
  26. if r.errToReturn != nil {
  27. return n, r.errToReturn
  28. }
  29. // Return io.EOF along with the bytes.
  30. return n, io.EOF
  31. }
  32. // TestDetectReader tests the DetectReader function.
  33. func TestDetectReader(t *testing.T) {
  34. tests := []struct {
  35. name string
  36. reader io.Reader
  37. bufSize int
  38. findingsCount int
  39. }{
  40. {
  41. name: "Test case - Reader returns n > 0 bytes and nil error",
  42. bufSize: 10,
  43. findingsCount: 1,
  44. reader: strings.NewReader(secret),
  45. },
  46. {
  47. name: "Test case - Reader returns n > 0 bytes and io.EOF error",
  48. bufSize: 10,
  49. findingsCount: 1,
  50. reader: &mockReader{
  51. data: []byte(secret),
  52. },
  53. },
  54. }
  55. for _, test := range tests {
  56. t.Run(test.name, func(t *testing.T) {
  57. detector, err := NewDetectorDefaultConfig()
  58. require.NoError(t, err)
  59. findings, err := detector.DetectReader(test.reader, test.bufSize)
  60. require.NoError(t, err)
  61. assert.Equal(t, test.findingsCount, len(findings))
  62. })
  63. }
  64. }
  65. func TestStreamDetectReader(t *testing.T) {
  66. tests := []struct {
  67. name string
  68. reader io.Reader
  69. bufSize int
  70. expectedCount int
  71. expectError bool
  72. }{
  73. {
  74. name: "Single secret streaming",
  75. bufSize: 10,
  76. expectedCount: 1,
  77. reader: strings.NewReader(secret),
  78. expectError: false,
  79. },
  80. {
  81. name: "Empty reader",
  82. bufSize: 10,
  83. expectedCount: 0,
  84. reader: strings.NewReader(""),
  85. expectError: false,
  86. },
  87. {
  88. name: "Reader returns error",
  89. bufSize: 10,
  90. expectedCount: 0,
  91. reader: iotest.ErrReader(errors.New("simulated read error")),
  92. expectError: true,
  93. },
  94. {
  95. name: "Multiple secrets with larger buffer",
  96. bufSize: 20,
  97. expectedCount: 2,
  98. reader: strings.NewReader(secret + "\n" + secret),
  99. expectError: false,
  100. },
  101. {
  102. name: "Mock reader with EOF",
  103. bufSize: 10,
  104. expectedCount: 1,
  105. reader: &mockReader{data: []byte(secret)},
  106. expectError: false,
  107. },
  108. {
  109. name: "Secret split across boundary",
  110. bufSize: 1, // 1KB buffer forces multiple reads
  111. expectedCount: 1,
  112. reader: io.MultiReader(
  113. strings.NewReader(secret[:len(secret)/2]),
  114. strings.NewReader(secret[len(secret)/2:])),
  115. expectError: false,
  116. },
  117. {
  118. name: "Reader returns error after first read",
  119. bufSize: 1,
  120. expectedCount: 0,
  121. reader: &mockReader{
  122. data: append(bytes.Repeat([]byte("blah"), 1000), []byte(secret)...),
  123. errToReturn: errors.New("simulated read error"),
  124. },
  125. expectError: true,
  126. },
  127. }
  128. for _, test := range tests {
  129. t.Run(test.name, func(t *testing.T) {
  130. detector, err := NewDetectorDefaultConfig()
  131. require.NoError(t, err)
  132. findingsCh, errCh := detector.StreamDetectReader(test.reader, test.bufSize)
  133. var findings []report.Finding
  134. for f := range findingsCh {
  135. findings = append(findings, f)
  136. }
  137. finalErr := <-errCh
  138. if test.expectError {
  139. require.Error(t, finalErr)
  140. } else {
  141. require.NoError(t, finalErr)
  142. }
  143. assert.Equal(t, test.expectedCount, len(findings))
  144. })
  145. }
  146. }