177 lines
5.5 KiB
Go
177 lines
5.5 KiB
Go
package buffer
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestProcessResponseAsRingBufferToEnd(t *testing.T) {
|
|
t.Run("normal lines", func(t *testing.T) {
|
|
body := "line1\nline2\nline3\n"
|
|
resp := &http.Response{
|
|
Body: io.NopCloser(strings.NewReader(body)),
|
|
}
|
|
|
|
result, totalLines, respOut, err := ProcessResponseAsRingBufferToEnd(resp, 10)
|
|
if respOut != nil && respOut.Body != nil {
|
|
defer respOut.Body.Close()
|
|
}
|
|
require.NoError(t, err)
|
|
assert.Equal(t, 3, totalLines)
|
|
assert.Equal(t, "line1\nline2\nline3", result)
|
|
})
|
|
|
|
t.Run("ring buffer keeps last N lines", func(t *testing.T) {
|
|
body := "line1\nline2\nline3\nline4\nline5\n"
|
|
resp := &http.Response{
|
|
Body: io.NopCloser(strings.NewReader(body)),
|
|
}
|
|
|
|
result, totalLines, respOut, err := ProcessResponseAsRingBufferToEnd(resp, 3)
|
|
if respOut != nil && respOut.Body != nil {
|
|
defer respOut.Body.Close()
|
|
}
|
|
require.NoError(t, err)
|
|
assert.Equal(t, 5, totalLines)
|
|
assert.Equal(t, "line3\nline4\nline5", result)
|
|
})
|
|
|
|
t.Run("handles very long line exceeding 10MB", func(t *testing.T) {
|
|
// Create a line that exceeds maxLineSize (10MB)
|
|
longLine := strings.Repeat("x", 11*1024*1024) // 11MB
|
|
body := "line1\n" + longLine + "\nline3\n"
|
|
resp := &http.Response{
|
|
Body: io.NopCloser(strings.NewReader(body)),
|
|
}
|
|
|
|
result, totalLines, respOut, err := ProcessResponseAsRingBufferToEnd(resp, 100)
|
|
if respOut != nil && respOut.Body != nil {
|
|
defer respOut.Body.Close()
|
|
}
|
|
require.NoError(t, err)
|
|
// Should have processed lines with truncation marker
|
|
assert.Greater(t, totalLines, 0)
|
|
assert.Contains(t, result, "TRUNCATED")
|
|
})
|
|
|
|
t.Run("handles line at exactly max size", func(t *testing.T) {
|
|
// Create a line just under maxLineSize
|
|
longLine := strings.Repeat("a", 1024*1024) // 1MB - should work fine
|
|
body := "start\n" + longLine + "\nend\n"
|
|
resp := &http.Response{
|
|
Body: io.NopCloser(strings.NewReader(body)),
|
|
}
|
|
|
|
result, totalLines, respOut, err := ProcessResponseAsRingBufferToEnd(resp, 100)
|
|
if respOut != nil && respOut.Body != nil {
|
|
defer respOut.Body.Close()
|
|
}
|
|
require.NoError(t, err)
|
|
assert.Equal(t, 3, totalLines)
|
|
assert.Contains(t, result, "start")
|
|
assert.Contains(t, result, "end")
|
|
})
|
|
|
|
t.Run("ring buffer with long line in middle of many lines", func(t *testing.T) {
|
|
// Create many lines with a long line in the middle
|
|
// Ring buffer size is 5, so we should only keep the last 5 lines
|
|
var sb strings.Builder
|
|
for i := 1; i <= 10; i++ {
|
|
sb.WriteString(fmt.Sprintf("line%d\n", i))
|
|
}
|
|
// Insert an 11MB line (exceeds maxLineSize of 10MB)
|
|
longLine := strings.Repeat("x", 11*1024*1024)
|
|
sb.WriteString(longLine)
|
|
sb.WriteString("\n")
|
|
for i := 11; i <= 20; i++ {
|
|
sb.WriteString(fmt.Sprintf("line%d\n", i))
|
|
}
|
|
|
|
resp := &http.Response{
|
|
Body: io.NopCloser(strings.NewReader(sb.String())),
|
|
}
|
|
|
|
result, totalLines, respOut, err := ProcessResponseAsRingBufferToEnd(resp, 5)
|
|
if respOut != nil && respOut.Body != nil {
|
|
defer respOut.Body.Close()
|
|
}
|
|
require.NoError(t, err)
|
|
// 10 lines before + 1 long line + 10 lines after = 21 total
|
|
assert.Equal(t, 21, totalLines)
|
|
// Should only have the last 5 lines (line16 through line20)
|
|
assert.Contains(t, result, "line16")
|
|
assert.Contains(t, result, "line17")
|
|
assert.Contains(t, result, "line18")
|
|
assert.Contains(t, result, "line19")
|
|
assert.Contains(t, result, "line20")
|
|
// Should NOT contain earlier lines
|
|
assert.NotContains(t, result, "line1\n")
|
|
assert.NotContains(t, result, "line10\n")
|
|
// The truncated line should not be in the last 5
|
|
assert.NotContains(t, result, "TRUNCATED")
|
|
})
|
|
|
|
t.Run("empty response body", func(t *testing.T) {
|
|
resp := &http.Response{
|
|
Body: io.NopCloser(strings.NewReader("")),
|
|
}
|
|
|
|
result, totalLines, respOut, err := ProcessResponseAsRingBufferToEnd(resp, 10)
|
|
if respOut != nil && respOut.Body != nil {
|
|
defer respOut.Body.Close()
|
|
}
|
|
require.NoError(t, err)
|
|
assert.Equal(t, 0, totalLines)
|
|
assert.Equal(t, "", result)
|
|
})
|
|
|
|
t.Run("line at exactly maxLineSize boundary", func(t *testing.T) {
|
|
// Create a line at exactly maxLineSize (10MB) - should be truncated
|
|
exactLine := strings.Repeat("z", 10*1024*1024)
|
|
body := "before\n" + exactLine + "\nafter\n"
|
|
resp := &http.Response{
|
|
Body: io.NopCloser(strings.NewReader(body)),
|
|
}
|
|
|
|
result, totalLines, respOut, err := ProcessResponseAsRingBufferToEnd(resp, 10)
|
|
if respOut != nil && respOut.Body != nil {
|
|
defer respOut.Body.Close()
|
|
}
|
|
require.NoError(t, err)
|
|
assert.Equal(t, 3, totalLines)
|
|
assert.Contains(t, result, "before")
|
|
assert.Contains(t, result, "TRUNCATED")
|
|
assert.Contains(t, result, "after")
|
|
})
|
|
|
|
t.Run("ring buffer keeps truncated line when in last N", func(t *testing.T) {
|
|
// Long line followed by only 2 more lines, with ring buffer size 5
|
|
longLine := strings.Repeat("y", 11*1024*1024)
|
|
body := "line1\nline2\nline3\n" + longLine + "\nlineA\nlineB\n"
|
|
resp := &http.Response{
|
|
Body: io.NopCloser(strings.NewReader(body)),
|
|
}
|
|
|
|
result, totalLines, respOut, err := ProcessResponseAsRingBufferToEnd(resp, 5)
|
|
if respOut != nil && respOut.Body != nil {
|
|
defer respOut.Body.Close()
|
|
}
|
|
require.NoError(t, err)
|
|
assert.Equal(t, 6, totalLines)
|
|
// Last 5: line2, line3, truncated, lineA, lineB
|
|
assert.Contains(t, result, "line2")
|
|
assert.Contains(t, result, "line3")
|
|
assert.Contains(t, result, "TRUNCATED")
|
|
assert.Contains(t, result, "lineA")
|
|
assert.Contains(t, result, "lineB")
|
|
// line1 should be rotated out
|
|
assert.NotContains(t, result, "line1")
|
|
})
|
|
}
|