blob: 90dcf98b1dbb680554932a473cd65484a0817364 [file] [log] [blame]
// Copyright 2017 The Upspin Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"bytes"
"fmt"
"math/rand"
"strconv"
"strings"
"testing"
)
func TestRollingLog(t *testing.T) {
oldMax := maxBacklog
defer func() { maxBacklog = oldMax }()
maxBacklog = 1024
l := rollingLog{}
for i := 0; i < 2000; i++ {
n := rand.Intn(100)
fmt.Fprintf(&l, "%.2d%s\n", n, strings.Repeat("n", n))
err := validate(l.Log())
if err != nil {
t.Fatalf("iteration %d: %v", n, err)
}
}
// Write a >maxBacklog string of m's and n's;
// it should just replace the log.
mm := strings.Repeat("m", 512)
nn := strings.Repeat("n", 512)
want := fmt.Sprintf("%s\n%s\n", mm, nn)
l.Write([]byte(want))
if got := string(l.Log()); got != want {
t.Fatalf("mismatch after long write\ngot %d bytes: %q\nwant %d bytes: %q",
len(got), got, len(want), want)
}
// Now this next write should leave us with
// the run of n's followed by "hello".
s := "hello\n"
l.Write([]byte(s))
want = fmt.Sprintf("%s\n%s", nn, s)
if got := string(l.Log()); got != want {
t.Fatalf("mismatch after short write after long write\ngot %d bytes: %q\nwant %d bytes: %q",
len(got), got, len(want), want)
}
}
func validate(b []byte) error {
lines := bytes.Split(b, []byte("\n"))
for i, l := range lines {
if len(l) == 0 {
if i != len(lines)-1 {
return fmt.Errorf("found empty line mid-log at %d", i)
}
return nil
}
if len(l) < 2 {
return fmt.Errorf("line %d too short", i)
}
n, err := strconv.Atoi(string(l[:2]))
if err != nil {
return fmt.Errorf("invalid length of line %d: %v", i, err)
}
if !bytes.Equal(l[2:], bytes.Repeat([]byte("n"), n)) {
return fmt.Errorf("bad line %d: %q", i, l)
}
}
return nil
}