105 lines
3.0 KiB
Go
105 lines
3.0 KiB
Go
package tasks
|
|
|
|
import (
|
|
"bytes"
|
|
"testing"
|
|
)
|
|
|
|
func TestTinyLog_UTF8Splitting(t *testing.T) {
|
|
tl, err := NewTinyLog("test-utf8", nil)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create TinyLog: %v", err)
|
|
}
|
|
defer tl.Close()
|
|
|
|
// "你好" in UTF-8: E4 BD A0, E5 a5 bd
|
|
part1 := []byte{0xE4, 0xBD} // Partial "你"
|
|
part2 := []byte{0xA0, 0xE5, 0xA5} // Rest of "你", partial "好"
|
|
part3 := []byte{0xBD, '\n'} // Rest of "好", newline
|
|
|
|
_, _ = tl.Write(part1)
|
|
if len(tl.remainder) != 2 {
|
|
t.Errorf("Expected remainder len 2, got %d", len(tl.remainder))
|
|
}
|
|
|
|
_, _ = tl.Write(part2)
|
|
// Currently it should collect both parts but still no newline,
|
|
// so remainder should be 5 bytes.
|
|
if len(tl.remainder) != 5 {
|
|
t.Errorf("Expected remainder len 5, got %d", len(tl.remainder))
|
|
}
|
|
|
|
_, _ = tl.Write(part3)
|
|
if len(tl.remainder) != 0 {
|
|
t.Errorf("Expected remainder len 0 after newline, got %d", len(tl.remainder))
|
|
}
|
|
|
|
// Read and verify
|
|
data, err := tl.ReadLastLines(1)
|
|
if err != nil {
|
|
t.Fatalf("ReadLastLines failed: %v", err)
|
|
}
|
|
if !bytes.Contains(data, []byte("你好")) {
|
|
t.Errorf("Expected output to contain '你好', got %q", data)
|
|
}
|
|
}
|
|
|
|
func TestTinyLog_CarriageReturn(t *testing.T) {
|
|
tl, err := NewTinyLog("test-cr", nil)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create TinyLog: %v", err)
|
|
}
|
|
defer tl.Close()
|
|
|
|
input := []byte("progress: 50%\rprogress: 100%\r\n")
|
|
_, _ = tl.Write(input)
|
|
|
|
data, err := tl.ReadLastLines(10)
|
|
if err != nil {
|
|
t.Fatalf("ReadLastLines failed: %v", err)
|
|
}
|
|
|
|
// Should contain both progress lines (or at least be split correctly)
|
|
if !bytes.Contains(data, []byte("progress: 50%")) {
|
|
t.Errorf("Expected output to contain 'progress: 50%%', got %q", data)
|
|
}
|
|
if !bytes.Contains(data, []byte("progress: 100%")) {
|
|
t.Errorf("Expected output to contain 'progress: 100%%', got %q", data)
|
|
}
|
|
}
|
|
|
|
func TestTinyLog_LongLineCut(t *testing.T) {
|
|
tl, err := NewTinyLog("test-long", nil)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create TinyLog: %v", err)
|
|
}
|
|
defer tl.Close()
|
|
|
|
// Create a buffer of maxLogBufferLen-1 bytes with a multi-byte character at the maxLogBufferLen boundary
|
|
// We want to ensure it doesn't cut in the middle of a 3-byte char.
|
|
longData := make([]byte, maxLogBufferLen-1)
|
|
for i := range longData {
|
|
longData[i] = 'A'
|
|
}
|
|
// "你" is E4 BD A0
|
|
longData = append(longData, 0xE4, 0xBD, 0xA0) // This starts at index maxLogBufferLen-1.
|
|
// Index maxLogBufferLen-1: E4
|
|
// Index maxLogBufferLen: BD
|
|
// Index maxLogBufferLen+1: A0
|
|
// If we cut at maxLogBufferLen, we split E4 and BD.
|
|
|
|
_, _ = tl.Write(longData)
|
|
|
|
// Since it's > maxLogBufferLen and no newline, it should trigger the cut.
|
|
// Our logic finds the last safe boundary before maxLogBufferLen.
|
|
// RuneStart(E4) at maxLogBufferLen-1 is true. FullRune(E4 at maxLogBufferLen-1 in payload[:maxLogBufferLen]) is false.
|
|
// So lastSafe should be maxLogBufferLen-1.
|
|
|
|
// The first maxLogBufferLen-1 bytes (all 'A') should be processed.
|
|
// The "你" should be in remainder.
|
|
|
|
if len(tl.remainder) != 3 {
|
|
t.Errorf("Expected remainder len 3 (the char '你'), got %d", len(tl.remainder))
|
|
}
|
|
}
|