@@ -7,11 +7,13 @@ import (
77 "fmt"
88 "log"
99 "os"
10+ "path/filepath"
1011 "strings"
1112 "testing"
1213 "time"
1314
1415 "github.com/stretchr/testify/assert"
16+ "github.com/stretchr/testify/require"
1517)
1618
1719const linesWrittenToFile int = 10
@@ -197,3 +199,100 @@ func tearDown(tmpfile *os.File) {
197199 exitOnDeletionCheckDuration = time .Minute
198200 exitOnDeletionWaitDuration = 5 * time .Minute
199201}
202+
203+ func TestUtf16LineSize (t * testing.T ) {
204+ tmpfile , err := os .CreateTemp ("" , "" )
205+ require .NoError (t , err )
206+ defer os .Remove (tmpfile .Name ())
207+
208+ // Create a UTF-16 BOM
209+ _ , err = tmpfile .Write ([]byte {0xFE , 0xFF })
210+ require .NoError (t , err )
211+
212+ // Create a tail with a small MaxLineSize
213+ maxLineSize := 100
214+ tail , err := TailFile (tmpfile .Name (), Config {
215+ MaxLineSize : maxLineSize ,
216+ Follow : true ,
217+ ReOpen : false ,
218+ Poll : true ,
219+ })
220+ require .NoError (t , err )
221+ defer tail .Stop ()
222+
223+ // Write a UTF-16 encoded line that exceeds MaxLineSize when decoded
224+ // Each 'a' will be 2 bytes in UTF-16
225+ utf16Line := make ([]byte , 0 , maxLineSize * 4 )
226+ for i := 0 ; i < maxLineSize * 2 ; i ++ {
227+ utf16Line = append (utf16Line , 0x00 , 'a' )
228+ }
229+ utf16Line = append (utf16Line , 0x00 , '\n' )
230+
231+ _ , err = tmpfile .Write (utf16Line )
232+ require .NoError (t , err )
233+ err = tmpfile .Sync ()
234+ require .NoError (t , err )
235+
236+ // Read the line and verify it's truncated
237+ select {
238+ case line := <- tail .Lines :
239+ // The line should be truncated to maxLineSize
240+ assert .LessOrEqual (t , len (line .Text ), maxLineSize )
241+ case <- time .After (1 * time .Second ):
242+ t .Fatal ("timeout waiting for line" )
243+ }
244+ }
245+
246+ func TestTail_DefaultBuffer (t * testing.T ) {
247+ // Test that default buffer works with normal-sized log lines
248+ tempDir := t .TempDir ()
249+ filename := filepath .Join (tempDir , "test.log" )
250+
251+ // Create a file with a normal-sized line (1KB - well within default buffer)
252+ normalContent := strings .Repeat ("b" , 1024 ) // 1KB
253+ err := os .WriteFile (filename , []byte (normalContent + "\n " ), 0600 )
254+ require .NoError (t , err )
255+
256+ tail , err := TailFile (filename , Config {
257+ Follow : false ,
258+ MustExist : true ,
259+ // MaxLineSize not set - should use default buffer
260+ })
261+ require .NoError (t , err )
262+ defer tail .Stop ()
263+
264+ select {
265+ case line := <- tail .Lines :
266+ assert .NoError (t , line .Err )
267+ assert .Equal (t , normalContent , line .Text )
268+ case <- time .After (time .Second ):
269+ t .Fatal ("Timeout waiting for line" )
270+ }
271+ }
272+
273+ func TestTail_1MBWithExplicitMaxLineSize (t * testing.T ) {
274+ // Test that large lines work when MaxLineSize is explicitly set
275+ tempDir := t .TempDir ()
276+ filename := filepath .Join (tempDir , "test.log" )
277+
278+ // Create a file with a 512KB line
279+ largeContent := strings .Repeat ("b" , 512 * 1024 ) // 512KB
280+ err := os .WriteFile (filename , []byte (largeContent + "\n " ), 0600 )
281+ require .NoError (t , err )
282+
283+ tail , err := TailFile (filename , Config {
284+ Follow : false ,
285+ MustExist : true ,
286+ MaxLineSize : 1024 * 1024 , // Explicitly set 1MB buffer
287+ })
288+ require .NoError (t , err )
289+ defer tail .Stop ()
290+
291+ select {
292+ case line := <- tail .Lines :
293+ assert .NoError (t , line .Err )
294+ assert .Equal (t , largeContent , line .Text )
295+ case <- time .After (time .Second ):
296+ t .Fatal ("Timeout waiting for line" )
297+ }
298+ }
0 commit comments