package cursor_test import ( "fmt" "testing" "time" "github.com/tendermint/tendermint/internal/eventlog/cursor" ) func mustParse(t *testing.T, s string) cursor.Cursor { t.Helper() var c cursor.Cursor if err := c.UnmarshalText([]byte(s)); err != nil { t.Fatalf("Unmarshal %q: unexpected error: %v", s, err) } return c } func TestSource_counter(t *testing.T) { src := &cursor.Source{ TimeIndex: func() int64 { return 255 }, } for i := 1; i <= 5; i++ { want := fmt.Sprintf("00000000000000ff-%04x", i) got := src.Cursor().String() if got != want { t.Errorf("Cursor %d: got %q, want %q", i, got, want) } } } func TestSource_timeIndex(t *testing.T) { times := []int64{0, 1, 100, 65535, 0x76543210fecdba98} src := &cursor.Source{ TimeIndex: func() int64 { out := times[0] times = append(times[1:], out) return out }, Counter: 160, } results := []string{ "0000000000000000-00a1", "0000000000000001-00a2", "0000000000000064-00a3", "000000000000ffff-00a4", "76543210fecdba98-00a5", } for i, want := range results { if got := src.Cursor().String(); got != want { t.Errorf("Cursor %d: got %q, want %q", i+1, got, want) } } } func TestCursor_roundTrip(t *testing.T) { const text = `0123456789abcdef-fce9` c := mustParse(t, text) if got := c.String(); got != text { t.Errorf("Wrong string format: got %q, want %q", got, text) } cmp, err := c.MarshalText() if err != nil { t.Fatalf("Marshal %+v failed: %v", c, err) } if got := string(cmp); got != text { t.Errorf("Wrong text format: got %q, want %q", got, text) } } func TestCursor_ordering(t *testing.T) { // Condition: text1 precedes text2 in time order. // Condition: text2 has an earlier sequence than text1. const zero = "" const text1 = "0000000012345678-0005" const text2 = "00000000fecdeba9-0002" zc := mustParse(t, zero) c1 := mustParse(t, text1) c2 := mustParse(t, text2) // Confirm for all pairs that string order respects time order. pairs := []struct { t1, t2 string c1, c2 cursor.Cursor }{ {zero, zero, zc, zc}, {zero, text1, zc, c1}, {zero, text2, zc, c2}, {text1, zero, c1, zc}, {text1, text1, c1, c1}, {text1, text2, c1, c2}, {text2, zero, c2, zc}, {text2, text1, c2, c1}, {text2, text2, c2, c2}, } for _, pair := range pairs { want := pair.t1 < pair.t2 if got := pair.c1.Before(pair.c2); got != want { t.Errorf("(%s).Before(%s): got %v, want %v", pair.t1, pair.t2, got, want) } } } func TestCursor_IsZero(t *testing.T) { tests := []struct { text string want bool }{ {"", true}, {"0000000000000000-0000", true}, {"0000000000000001-0000", false}, {"0000000000000000-0001", false}, {"0000000000000001-0001", false}, } for _, test := range tests { c := mustParse(t, test.text) if got := c.IsZero(); got != test.want { t.Errorf("IsZero(%q): got %v, want %v", test.text, got, test.want) } } } func TestCursor_Diff(t *testing.T) { const time1 = 0x1ac0193001 const time2 = 0x0ac0193001 text1 := fmt.Sprintf("%016x-0001", time1) text2 := fmt.Sprintf("%016x-0005", time2) want := time.Duration(time1 - time2) c1 := mustParse(t, text1) c2 := mustParse(t, text2) got := c1.Diff(c2) if got != want { t.Fatalf("Diff %q - %q: got %v, want %v", text1, text2, got, want) } }