github.com/elves/elvish@v0.15.0/pkg/cli/histutil/hybrid_store_test.go (about)

     1  package histutil
     2  
     3  import (
     4  	"errors"
     5  	"reflect"
     6  	"testing"
     7  
     8  	"github.com/elves/elvish/pkg/store"
     9  )
    10  
    11  var errMock = errors.New("mock error")
    12  
    13  func TestNewHybridStore_ReturnsMemStoreIfDBIsNil(t *testing.T) {
    14  	store, err := NewHybridStore(nil)
    15  	if _, ok := store.(*memStore); !ok {
    16  		t.Errorf("NewHybridStore -> %v, want memStore", store)
    17  	}
    18  	if err != nil {
    19  		t.Errorf("NewHybridStore -> error %v, want nil", err)
    20  	}
    21  }
    22  
    23  func TestNewHybridStore_ReturnsMemStoreOnDBError(t *testing.T) {
    24  	db := NewFaultyInMemoryDB()
    25  	db.SetOneOffError(errMock)
    26  	store, err := NewHybridStore(db)
    27  	if _, ok := store.(*memStore); !ok {
    28  		t.Errorf("NewHybridStore -> %v, want memStore", store)
    29  	}
    30  	if err != errMock {
    31  		t.Errorf("NewHybridStore -> error %v, want %v", err, errMock)
    32  	}
    33  }
    34  
    35  func TestFusuer_AddCmd_AddsBothToDBAndSession(t *testing.T) {
    36  	db := NewFaultyInMemoryDB("shared 1")
    37  	f := mustNewHybridStore(db)
    38  
    39  	f.AddCmd(store.Cmd{Text: "session 1"})
    40  
    41  	wantDBCmds := []store.Cmd{
    42  		{Text: "shared 1", Seq: 0}, {Text: "session 1", Seq: 1}}
    43  	if dbCmds, _ := db.CmdsWithSeq(-1, -1); !reflect.DeepEqual(dbCmds, wantDBCmds) {
    44  		t.Errorf("DB commands = %v, want %v", dbCmds, wantDBCmds)
    45  	}
    46  
    47  	allCmds, err := f.AllCmds()
    48  	if err != nil {
    49  		panic(err)
    50  	}
    51  	wantAllCmds := []store.Cmd{
    52  		{Text: "shared 1", Seq: 0},
    53  		{Text: "session 1", Seq: 1}}
    54  	if !reflect.DeepEqual(allCmds, wantAllCmds) {
    55  		t.Errorf("AllCmd -> %v, want %v", allCmds, wantAllCmds)
    56  	}
    57  }
    58  
    59  func TestHybridStore_AddCmd_AddsToSessionEvenIfDBErrors(t *testing.T) {
    60  	db := NewFaultyInMemoryDB()
    61  	f := mustNewHybridStore(db)
    62  	db.SetOneOffError(errMock)
    63  
    64  	_, err := f.AddCmd(store.Cmd{Text: "haha"})
    65  	if err != errMock {
    66  		t.Errorf("AddCmd -> error %v, want %v", err, errMock)
    67  	}
    68  
    69  	allCmds, err := f.AllCmds()
    70  	if err != nil {
    71  		panic(err)
    72  	}
    73  	wantAllCmds := []store.Cmd{{Text: "haha", Seq: 1}}
    74  	if !reflect.DeepEqual(allCmds, wantAllCmds) {
    75  		t.Errorf("AllCmd -> %v, want %v", allCmds, wantAllCmds)
    76  	}
    77  }
    78  
    79  func TestHybridStore_AllCmds_IncludesFrozenSharedAndNewlyAdded(t *testing.T) {
    80  	db := NewFaultyInMemoryDB("shared 1")
    81  	f := mustNewHybridStore(db)
    82  
    83  	// Simulate adding commands from both the current session and other sessions.
    84  	f.AddCmd(store.Cmd{Text: "session 1"})
    85  	db.AddCmd("other session 1")
    86  	db.AddCmd("other session 2")
    87  	f.AddCmd(store.Cmd{Text: "session 2"})
    88  	db.AddCmd("other session 3")
    89  
    90  	// AllCmds should return all commands from the storage when the HybridStore
    91  	// was created, plus session commands. The session commands should have
    92  	// sequence numbers consistent with the DB.
    93  	allCmds, err := f.AllCmds()
    94  	if err != nil {
    95  		t.Errorf("AllCmds -> error %v, want nil", err)
    96  	}
    97  	wantAllCmds := []store.Cmd{
    98  		{Text: "shared 1", Seq: 0},
    99  		{Text: "session 1", Seq: 1},
   100  		{Text: "session 2", Seq: 4}}
   101  	if !reflect.DeepEqual(allCmds, wantAllCmds) {
   102  		t.Errorf("AllCmds -> %v, want %v", allCmds, wantAllCmds)
   103  	}
   104  }
   105  
   106  func TestHybridStore_AllCmds_ReturnsSessionIfDBErrors(t *testing.T) {
   107  	db := NewFaultyInMemoryDB("shared 1")
   108  	f := mustNewHybridStore(db)
   109  	f.AddCmd(store.Cmd{Text: "session 1"})
   110  	db.SetOneOffError(errMock)
   111  
   112  	allCmds, err := f.AllCmds()
   113  	if err != errMock {
   114  		t.Errorf("AllCmds -> error %v, want %v", err, errMock)
   115  	}
   116  	wantAllCmds := []store.Cmd{{Text: "session 1", Seq: 1}}
   117  	if !reflect.DeepEqual(allCmds, wantAllCmds) {
   118  		t.Errorf("AllCmd -> %v, want %v", allCmds, wantAllCmds)
   119  	}
   120  }
   121  
   122  func TestHybridStore_Cursor_OnlySession(t *testing.T) {
   123  	db := NewFaultyInMemoryDB()
   124  	f := mustNewHybridStore(db)
   125  	db.AddCmd("+ other session")
   126  	f.AddCmd(store.Cmd{Text: "+ session 1"})
   127  	f.AddCmd(store.Cmd{Text: "- no match"})
   128  
   129  	testCursorIteration(t, f.Cursor("+"), []store.Cmd{{Text: "+ session 1", Seq: 1}})
   130  }
   131  
   132  func TestHybridStore_Cursor_OnlyShared(t *testing.T) {
   133  	db := NewFaultyInMemoryDB("- no match", "+ shared 1")
   134  	f := mustNewHybridStore(db)
   135  	db.AddCmd("+ other session")
   136  	f.AddCmd(store.Cmd{Text: "- no match"})
   137  
   138  	testCursorIteration(t, f.Cursor("+"), []store.Cmd{{Text: "+ shared 1", Seq: 1}})
   139  }
   140  
   141  func TestHybridStore_Cursor_SharedAndSession(t *testing.T) {
   142  	db := NewFaultyInMemoryDB("- no match", "+ shared 1")
   143  	f := mustNewHybridStore(db)
   144  	db.AddCmd("+ other session")
   145  	db.AddCmd("- no match")
   146  	f.AddCmd(store.Cmd{Text: "+ session 1"})
   147  	f.AddCmd(store.Cmd{Text: "- no match"})
   148  
   149  	testCursorIteration(t, f.Cursor("+"), []store.Cmd{
   150  		{Text: "+ shared 1", Seq: 1},
   151  		{Text: "+ session 1", Seq: 4}})
   152  }
   153  
   154  func testCursorIteration(t *testing.T, cursor Cursor, wantCmds []store.Cmd) {
   155  	expectEndOfHistory := func() {
   156  		t.Helper()
   157  		if _, err := cursor.Get(); err != ErrEndOfHistory {
   158  			t.Errorf("Get -> error %v, want ErrEndOfHistory", err)
   159  		}
   160  	}
   161  	expectCmd := func(i int) {
   162  		t.Helper()
   163  		wantCmd := wantCmds[i]
   164  		cmd, err := cursor.Get()
   165  		if cmd != wantCmd {
   166  			t.Errorf("Get -> %v, want %v", cmd, wantCmd)
   167  		}
   168  		if err != nil {
   169  			t.Errorf("Get -> error %v, want nil", err)
   170  		}
   171  	}
   172  
   173  	expectEndOfHistory()
   174  
   175  	for i := len(wantCmds) - 1; i >= 0; i-- {
   176  		cursor.Prev()
   177  		expectCmd(i)
   178  	}
   179  
   180  	cursor.Prev()
   181  	expectEndOfHistory()
   182  	cursor.Prev()
   183  	expectEndOfHistory()
   184  
   185  	for i := range wantCmds {
   186  		cursor.Next()
   187  		expectCmd(i)
   188  	}
   189  
   190  	cursor.Next()
   191  	expectEndOfHistory()
   192  	cursor.Next()
   193  	expectEndOfHistory()
   194  }
   195  
   196  func mustNewHybridStore(db DB) Store {
   197  	f, err := NewHybridStore(db)
   198  	if err != nil {
   199  		panic(err)
   200  	}
   201  	return f
   202  }