| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | // Copyright 2018 The go-ethereum Authors | 
					
						
							|  |  |  | // This file is part of the go-ethereum library. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							|  |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							|  |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package shed | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							|  |  |  | 	"encoding/binary" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"sort" | 
					
						
							|  |  |  | 	"testing" | 
					
						
							|  |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/syndtr/goleveldb/leveldb" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Index functions for the index that is used in tests in this file. | 
					
						
							|  |  |  | var retrievalIndexFuncs = IndexFuncs{ | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 	EncodeKey: func(fields Item) (key []byte, err error) { | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 		return fields.Address, nil | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 	DecodeKey: func(key []byte) (e Item, err error) { | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 		e.Address = key | 
					
						
							|  |  |  | 		return e, nil | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 	EncodeValue: func(fields Item) (value []byte, err error) { | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 		b := make([]byte, 8) | 
					
						
							|  |  |  | 		binary.BigEndian.PutUint64(b, uint64(fields.StoreTimestamp)) | 
					
						
							|  |  |  | 		value = append(b, fields.Data...) | 
					
						
							|  |  |  | 		return value, nil | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 	DecodeValue: func(keyItem Item, value []byte) (e Item, err error) { | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 		e.StoreTimestamp = int64(binary.BigEndian.Uint64(value[:8])) | 
					
						
							|  |  |  | 		e.Data = value[8:] | 
					
						
							|  |  |  | 		return e, nil | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // TestIndex validates put, get and delete functions of the Index implementation. | 
					
						
							|  |  |  | func TestIndex(t *testing.T) { | 
					
						
							|  |  |  | 	db, cleanupFunc := newTestDB(t) | 
					
						
							|  |  |  | 	defer cleanupFunc() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	index, err := db.NewIndex("retrieval", retrievalIndexFuncs) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("put", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		want := Item{ | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 			Address:        []byte("put-hash"), | 
					
						
							|  |  |  | 			Data:           []byte("DATA"), | 
					
						
							|  |  |  | 			StoreTimestamp: time.Now().UTC().UnixNano(), | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		err := index.Put(want) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		got, err := index.Get(Item{ | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 			Address: want.Address, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		checkItem(t, got, want) | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("overwrite", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 			want := Item{ | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 				Address:        []byte("put-hash"), | 
					
						
							|  |  |  | 				Data:           []byte("New DATA"), | 
					
						
							|  |  |  | 				StoreTimestamp: time.Now().UTC().UnixNano(), | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			err = index.Put(want) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				t.Fatal(err) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 			got, err := index.Get(Item{ | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 				Address: want.Address, | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				t.Fatal(err) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 			checkItem(t, got, want) | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 		}) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("put in batch", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		want := Item{ | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 			Address:        []byte("put-in-batch-hash"), | 
					
						
							|  |  |  | 			Data:           []byte("DATA"), | 
					
						
							|  |  |  | 			StoreTimestamp: time.Now().UTC().UnixNano(), | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		batch := new(leveldb.Batch) | 
					
						
							|  |  |  | 		index.PutInBatch(batch, want) | 
					
						
							|  |  |  | 		err := db.WriteBatch(batch) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		got, err := index.Get(Item{ | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 			Address: want.Address, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		checkItem(t, got, want) | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("overwrite", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 			want := Item{ | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 				Address:        []byte("put-in-batch-hash"), | 
					
						
							|  |  |  | 				Data:           []byte("New DATA"), | 
					
						
							|  |  |  | 				StoreTimestamp: time.Now().UTC().UnixNano(), | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			batch := new(leveldb.Batch) | 
					
						
							|  |  |  | 			index.PutInBatch(batch, want) | 
					
						
							|  |  |  | 			db.WriteBatch(batch) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				t.Fatal(err) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 			got, err := index.Get(Item{ | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 				Address: want.Address, | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				t.Fatal(err) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 			checkItem(t, got, want) | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 		}) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("put in batch twice", func(t *testing.T) { | 
					
						
							|  |  |  | 		// ensure that the last item of items with the same db keys | 
					
						
							|  |  |  | 		// is actually saved | 
					
						
							|  |  |  | 		batch := new(leveldb.Batch) | 
					
						
							|  |  |  | 		address := []byte("put-in-batch-twice-hash") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// put the first item | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		index.PutInBatch(batch, Item{ | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 			Address:        address, | 
					
						
							|  |  |  | 			Data:           []byte("DATA"), | 
					
						
							|  |  |  | 			StoreTimestamp: time.Now().UTC().UnixNano(), | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		want := Item{ | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 			Address:        address, | 
					
						
							|  |  |  | 			Data:           []byte("New DATA"), | 
					
						
							|  |  |  | 			StoreTimestamp: time.Now().UTC().UnixNano(), | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// then put the item that will produce the same key | 
					
						
							|  |  |  | 		// but different value in the database | 
					
						
							|  |  |  | 		index.PutInBatch(batch, want) | 
					
						
							|  |  |  | 		db.WriteBatch(batch) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		got, err := index.Get(Item{ | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 			Address: address, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		checkItem(t, got, want) | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("delete", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		want := Item{ | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 			Address:        []byte("delete-hash"), | 
					
						
							|  |  |  | 			Data:           []byte("DATA"), | 
					
						
							|  |  |  | 			StoreTimestamp: time.Now().UTC().UnixNano(), | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		err := index.Put(want) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		got, err := index.Get(Item{ | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 			Address: want.Address, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		checkItem(t, got, want) | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		err = index.Delete(Item{ | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 			Address: want.Address, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		wantErr := leveldb.ErrNotFound | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		got, err = index.Get(Item{ | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 			Address: want.Address, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		if err != wantErr { | 
					
						
							|  |  |  | 			t.Fatalf("got error %v, want %v", err, wantErr) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("delete in batch", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		want := Item{ | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 			Address:        []byte("delete-in-batch-hash"), | 
					
						
							|  |  |  | 			Data:           []byte("DATA"), | 
					
						
							|  |  |  | 			StoreTimestamp: time.Now().UTC().UnixNano(), | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		err := index.Put(want) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		got, err := index.Get(Item{ | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 			Address: want.Address, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		checkItem(t, got, want) | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		batch := new(leveldb.Batch) | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		index.DeleteInBatch(batch, Item{ | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 			Address: want.Address, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		err = db.WriteBatch(batch) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		wantErr := leveldb.ErrNotFound | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		got, err = index.Get(Item{ | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 			Address: want.Address, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		if err != wantErr { | 
					
						
							|  |  |  | 			t.Fatalf("got error %v, want %v", err, wantErr) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | // TestIndex_Iterate validates index Iterate | 
					
						
							|  |  |  | // functions for correctness. | 
					
						
							|  |  |  | func TestIndex_Iterate(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 	db, cleanupFunc := newTestDB(t) | 
					
						
							|  |  |  | 	defer cleanupFunc() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	index, err := db.NewIndex("retrieval", retrievalIndexFuncs) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 	items := []Item{ | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			Address: []byte("iterate-hash-01"), | 
					
						
							|  |  |  | 			Data:    []byte("data80"), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			Address: []byte("iterate-hash-03"), | 
					
						
							|  |  |  | 			Data:    []byte("data22"), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			Address: []byte("iterate-hash-05"), | 
					
						
							|  |  |  | 			Data:    []byte("data41"), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			Address: []byte("iterate-hash-02"), | 
					
						
							|  |  |  | 			Data:    []byte("data84"), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			Address: []byte("iterate-hash-06"), | 
					
						
							|  |  |  | 			Data:    []byte("data1"), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	batch := new(leveldb.Batch) | 
					
						
							|  |  |  | 	for _, i := range items { | 
					
						
							|  |  |  | 		index.PutInBatch(batch, i) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	err = db.WriteBatch(batch) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 	item04 := Item{ | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 		Address: []byte("iterate-hash-04"), | 
					
						
							|  |  |  | 		Data:    []byte("data0"), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	err = index.Put(item04) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	items = append(items, item04) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sort.SliceStable(items, func(i, j int) bool { | 
					
						
							|  |  |  | 		return bytes.Compare(items[i].Address, items[j].Address) < 0 | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("all", func(t *testing.T) { | 
					
						
							|  |  |  | 		var i int | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		err := index.Iterate(func(item Item) (stop bool, err error) { | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 			if i > len(items)-1 { | 
					
						
							|  |  |  | 				return true, fmt.Errorf("got unexpected index item: %#v", item) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			want := items[i] | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 			checkItem(t, item, want) | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 			i++ | 
					
						
							|  |  |  | 			return false, nil | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		}, nil) | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 	t.Run("start from", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 		startIndex := 2 | 
					
						
							|  |  |  | 		i := startIndex | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		err := index.Iterate(func(item Item) (stop bool, err error) { | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 			if i > len(items)-1 { | 
					
						
							|  |  |  | 				return true, fmt.Errorf("got unexpected index item: %#v", item) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			want := items[i] | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 			checkItem(t, item, want) | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 			i++ | 
					
						
							|  |  |  | 			return false, nil | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		}, &IterateOptions{ | 
					
						
							|  |  |  | 			StartFrom: &items[startIndex], | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("skip start from", func(t *testing.T) { | 
					
						
							|  |  |  | 		startIndex := 2 | 
					
						
							|  |  |  | 		i := startIndex + 1 | 
					
						
							|  |  |  | 		err := index.Iterate(func(item Item) (stop bool, err error) { | 
					
						
							|  |  |  | 			if i > len(items)-1 { | 
					
						
							|  |  |  | 				return true, fmt.Errorf("got unexpected index item: %#v", item) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			want := items[i] | 
					
						
							|  |  |  | 			checkItem(t, item, want) | 
					
						
							|  |  |  | 			i++ | 
					
						
							|  |  |  | 			return false, nil | 
					
						
							|  |  |  | 		}, &IterateOptions{ | 
					
						
							|  |  |  | 			StartFrom:         &items[startIndex], | 
					
						
							|  |  |  | 			SkipStartFromItem: true, | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 		}) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("stop", func(t *testing.T) { | 
					
						
							|  |  |  | 		var i int | 
					
						
							|  |  |  | 		stopIndex := 3 | 
					
						
							|  |  |  | 		var count int | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		err := index.Iterate(func(item Item) (stop bool, err error) { | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 			if i > len(items)-1 { | 
					
						
							|  |  |  | 				return true, fmt.Errorf("got unexpected index item: %#v", item) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			want := items[i] | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 			checkItem(t, item, want) | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 			count++ | 
					
						
							|  |  |  | 			if i == stopIndex { | 
					
						
							|  |  |  | 				return true, nil | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			i++ | 
					
						
							|  |  |  | 			return false, nil | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		}, nil) | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		wantItemsCount := stopIndex + 1 | 
					
						
							|  |  |  | 		if count != wantItemsCount { | 
					
						
							|  |  |  | 			t.Errorf("got %v items, expected %v", count, wantItemsCount) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("no overflow", func(t *testing.T) { | 
					
						
							|  |  |  | 		secondIndex, err := db.NewIndex("second-index", retrievalIndexFuncs) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		secondItem := Item{ | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 			Address: []byte("iterate-hash-10"), | 
					
						
							|  |  |  | 			Data:    []byte("data-second"), | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		err = secondIndex.Put(secondItem) | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		var i int | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		err = index.Iterate(func(item Item) (stop bool, err error) { | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 			if i > len(items)-1 { | 
					
						
							|  |  |  | 				return true, fmt.Errorf("got unexpected index item: %#v", item) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			want := items[i] | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 			checkItem(t, item, want) | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 			i++ | 
					
						
							|  |  |  | 			return false, nil | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		}, nil) | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		i = 0 | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		err = secondIndex.Iterate(func(item Item) (stop bool, err error) { | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 			if i > 1 { | 
					
						
							|  |  |  | 				return true, fmt.Errorf("got unexpected index item: %#v", item) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 			checkItem(t, item, secondItem) | 
					
						
							|  |  |  | 			i++ | 
					
						
							|  |  |  | 			return false, nil | 
					
						
							|  |  |  | 		}, nil) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // TestIndex_Iterate_withPrefix validates index Iterate | 
					
						
							|  |  |  | // function for correctness. | 
					
						
							|  |  |  | func TestIndex_Iterate_withPrefix(t *testing.T) { | 
					
						
							|  |  |  | 	db, cleanupFunc := newTestDB(t) | 
					
						
							|  |  |  | 	defer cleanupFunc() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	index, err := db.NewIndex("retrieval", retrievalIndexFuncs) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	allItems := []Item{ | 
					
						
							|  |  |  | 		{Address: []byte("want-hash-00"), Data: []byte("data80")}, | 
					
						
							|  |  |  | 		{Address: []byte("skip-hash-01"), Data: []byte("data81")}, | 
					
						
							|  |  |  | 		{Address: []byte("skip-hash-02"), Data: []byte("data82")}, | 
					
						
							|  |  |  | 		{Address: []byte("skip-hash-03"), Data: []byte("data83")}, | 
					
						
							|  |  |  | 		{Address: []byte("want-hash-04"), Data: []byte("data84")}, | 
					
						
							|  |  |  | 		{Address: []byte("want-hash-05"), Data: []byte("data85")}, | 
					
						
							|  |  |  | 		{Address: []byte("want-hash-06"), Data: []byte("data86")}, | 
					
						
							|  |  |  | 		{Address: []byte("want-hash-07"), Data: []byte("data87")}, | 
					
						
							|  |  |  | 		{Address: []byte("want-hash-08"), Data: []byte("data88")}, | 
					
						
							|  |  |  | 		{Address: []byte("want-hash-09"), Data: []byte("data89")}, | 
					
						
							|  |  |  | 		{Address: []byte("skip-hash-10"), Data: []byte("data90")}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	batch := new(leveldb.Batch) | 
					
						
							|  |  |  | 	for _, i := range allItems { | 
					
						
							|  |  |  | 		index.PutInBatch(batch, i) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	err = db.WriteBatch(batch) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	prefix := []byte("want") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	items := make([]Item, 0) | 
					
						
							|  |  |  | 	for _, item := range allItems { | 
					
						
							|  |  |  | 		if bytes.HasPrefix(item.Address, prefix) { | 
					
						
							|  |  |  | 			items = append(items, item) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	sort.SliceStable(items, func(i, j int) bool { | 
					
						
							|  |  |  | 		return bytes.Compare(items[i].Address, items[j].Address) < 0 | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("with prefix", func(t *testing.T) { | 
					
						
							|  |  |  | 		var i int | 
					
						
							|  |  |  | 		err := index.Iterate(func(item Item) (stop bool, err error) { | 
					
						
							|  |  |  | 			if i > len(items)-1 { | 
					
						
							|  |  |  | 				return true, fmt.Errorf("got unexpected index item: %#v", item) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			want := items[i] | 
					
						
							|  |  |  | 			checkItem(t, item, want) | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 			i++ | 
					
						
							|  |  |  | 			return false, nil | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		}, &IterateOptions{ | 
					
						
							|  |  |  | 			Prefix: prefix, | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 		}) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | 		if i != len(items) { | 
					
						
							|  |  |  | 			t.Errorf("got %v items, want %v", i, len(items)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("with prefix and start from", func(t *testing.T) { | 
					
						
							|  |  |  | 		startIndex := 2 | 
					
						
							|  |  |  | 		var count int | 
					
						
							|  |  |  | 		i := startIndex | 
					
						
							|  |  |  | 		err := index.Iterate(func(item Item) (stop bool, err error) { | 
					
						
							|  |  |  | 			if i > len(items)-1 { | 
					
						
							|  |  |  | 				return true, fmt.Errorf("got unexpected index item: %#v", item) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			want := items[i] | 
					
						
							|  |  |  | 			checkItem(t, item, want) | 
					
						
							|  |  |  | 			i++ | 
					
						
							|  |  |  | 			count++ | 
					
						
							|  |  |  | 			return false, nil | 
					
						
							|  |  |  | 		}, &IterateOptions{ | 
					
						
							|  |  |  | 			StartFrom: &items[startIndex], | 
					
						
							|  |  |  | 			Prefix:    prefix, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		wantCount := len(items) - startIndex | 
					
						
							|  |  |  | 		if count != wantCount { | 
					
						
							|  |  |  | 			t.Errorf("got %v items, want %v", count, wantCount) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("with prefix and skip start from", func(t *testing.T) { | 
					
						
							|  |  |  | 		startIndex := 2 | 
					
						
							|  |  |  | 		var count int | 
					
						
							|  |  |  | 		i := startIndex + 1 | 
					
						
							|  |  |  | 		err := index.Iterate(func(item Item) (stop bool, err error) { | 
					
						
							|  |  |  | 			if i > len(items)-1 { | 
					
						
							|  |  |  | 				return true, fmt.Errorf("got unexpected index item: %#v", item) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			want := items[i] | 
					
						
							|  |  |  | 			checkItem(t, item, want) | 
					
						
							|  |  |  | 			i++ | 
					
						
							|  |  |  | 			count++ | 
					
						
							|  |  |  | 			return false, nil | 
					
						
							|  |  |  | 		}, &IterateOptions{ | 
					
						
							|  |  |  | 			StartFrom:         &items[startIndex], | 
					
						
							|  |  |  | 			SkipStartFromItem: true, | 
					
						
							|  |  |  | 			Prefix:            prefix, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		wantCount := len(items) - startIndex - 1 | 
					
						
							|  |  |  | 		if count != wantCount { | 
					
						
							|  |  |  | 			t.Errorf("got %v items, want %v", count, wantCount) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("stop", func(t *testing.T) { | 
					
						
							|  |  |  | 		var i int | 
					
						
							|  |  |  | 		stopIndex := 3 | 
					
						
							|  |  |  | 		var count int | 
					
						
							|  |  |  | 		err := index.Iterate(func(item Item) (stop bool, err error) { | 
					
						
							|  |  |  | 			if i > len(items)-1 { | 
					
						
							|  |  |  | 				return true, fmt.Errorf("got unexpected index item: %#v", item) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			want := items[i] | 
					
						
							|  |  |  | 			checkItem(t, item, want) | 
					
						
							|  |  |  | 			count++ | 
					
						
							|  |  |  | 			if i == stopIndex { | 
					
						
							|  |  |  | 				return true, nil | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			i++ | 
					
						
							|  |  |  | 			return false, nil | 
					
						
							|  |  |  | 		}, &IterateOptions{ | 
					
						
							|  |  |  | 			Prefix: prefix, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		wantItemsCount := stopIndex + 1 | 
					
						
							|  |  |  | 		if count != wantItemsCount { | 
					
						
							|  |  |  | 			t.Errorf("got %v items, expected %v", count, wantItemsCount) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("no overflow", func(t *testing.T) { | 
					
						
							|  |  |  | 		secondIndex, err := db.NewIndex("second-index", retrievalIndexFuncs) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		secondItem := Item{ | 
					
						
							|  |  |  | 			Address: []byte("iterate-hash-10"), | 
					
						
							|  |  |  | 			Data:    []byte("data-second"), | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		err = secondIndex.Put(secondItem) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		var i int | 
					
						
							|  |  |  | 		err = index.Iterate(func(item Item) (stop bool, err error) { | 
					
						
							|  |  |  | 			if i > len(items)-1 { | 
					
						
							|  |  |  | 				return true, fmt.Errorf("got unexpected index item: %#v", item) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			want := items[i] | 
					
						
							|  |  |  | 			checkItem(t, item, want) | 
					
						
							|  |  |  | 			i++ | 
					
						
							|  |  |  | 			return false, nil | 
					
						
							|  |  |  | 		}, &IterateOptions{ | 
					
						
							|  |  |  | 			Prefix: prefix, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if i != len(items) { | 
					
						
							|  |  |  | 			t.Errorf("got %v items, want %v", i, len(items)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // TestIndex_count tests if Index.Count and Index.CountFrom | 
					
						
							|  |  |  | // returns the correct number of items. | 
					
						
							|  |  |  | func TestIndex_count(t *testing.T) { | 
					
						
							|  |  |  | 	db, cleanupFunc := newTestDB(t) | 
					
						
							|  |  |  | 	defer cleanupFunc() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	index, err := db.NewIndex("retrieval", retrievalIndexFuncs) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	items := []Item{ | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			Address: []byte("iterate-hash-01"), | 
					
						
							|  |  |  | 			Data:    []byte("data80"), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			Address: []byte("iterate-hash-02"), | 
					
						
							|  |  |  | 			Data:    []byte("data84"), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			Address: []byte("iterate-hash-03"), | 
					
						
							|  |  |  | 			Data:    []byte("data22"), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			Address: []byte("iterate-hash-04"), | 
					
						
							|  |  |  | 			Data:    []byte("data41"), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			Address: []byte("iterate-hash-05"), | 
					
						
							|  |  |  | 			Data:    []byte("data1"), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	batch := new(leveldb.Batch) | 
					
						
							|  |  |  | 	for _, i := range items { | 
					
						
							|  |  |  | 		index.PutInBatch(batch, i) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	err = db.WriteBatch(batch) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("Count", func(t *testing.T) { | 
					
						
							|  |  |  | 		got, err := index.Count() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		want := len(items) | 
					
						
							|  |  |  | 		if got != want { | 
					
						
							|  |  |  | 			t.Errorf("got %v items count, want %v", got, want) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("CountFrom", func(t *testing.T) { | 
					
						
							|  |  |  | 		got, err := index.CountFrom(Item{ | 
					
						
							|  |  |  | 			Address: items[1].Address, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		want := len(items) - 1 | 
					
						
							|  |  |  | 		if got != want { | 
					
						
							|  |  |  | 			t.Errorf("got %v items count, want %v", got, want) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// update the index with another item | 
					
						
							|  |  |  | 	t.Run("add item", func(t *testing.T) { | 
					
						
							|  |  |  | 		item04 := Item{ | 
					
						
							|  |  |  | 			Address: []byte("iterate-hash-06"), | 
					
						
							|  |  |  | 			Data:    []byte("data0"), | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		err = index.Put(item04) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		count := len(items) + 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("Count", func(t *testing.T) { | 
					
						
							|  |  |  | 			got, err := index.Count() | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				t.Fatal(err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			want := count | 
					
						
							|  |  |  | 			if got != want { | 
					
						
							|  |  |  | 				t.Errorf("got %v items count, want %v", got, want) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("CountFrom", func(t *testing.T) { | 
					
						
							|  |  |  | 			got, err := index.CountFrom(Item{ | 
					
						
							|  |  |  | 				Address: items[1].Address, | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				t.Fatal(err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			want := count - 1 | 
					
						
							|  |  |  | 			if got != want { | 
					
						
							|  |  |  | 				t.Errorf("got %v items count, want %v", got, want) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// delete some items | 
					
						
							|  |  |  | 	t.Run("delete items", func(t *testing.T) { | 
					
						
							|  |  |  | 		deleteCount := 3 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for _, item := range items[:deleteCount] { | 
					
						
							|  |  |  | 			err := index.Delete(item) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				t.Fatal(err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		count := len(items) + 1 - deleteCount | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("Count", func(t *testing.T) { | 
					
						
							|  |  |  | 			got, err := index.Count() | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				t.Fatal(err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			want := count | 
					
						
							|  |  |  | 			if got != want { | 
					
						
							|  |  |  | 				t.Errorf("got %v items count, want %v", got, want) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("CountFrom", func(t *testing.T) { | 
					
						
							|  |  |  | 			got, err := index.CountFrom(Item{ | 
					
						
							|  |  |  | 				Address: items[deleteCount+1].Address, | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				t.Fatal(err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			want := count - 1 | 
					
						
							|  |  |  | 			if got != want { | 
					
						
							|  |  |  | 				t.Errorf("got %v items count, want %v", got, want) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 	}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-07 13:20:11 +01:00
										 |  |  | // checkItem is a test helper function that compares if two Index items are the same. | 
					
						
							|  |  |  | func checkItem(t *testing.T, got, want Item) { | 
					
						
							| 
									
										
										
										
											2018-11-26 18:49:01 +01:00
										 |  |  | 	t.Helper() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if !bytes.Equal(got.Address, want.Address) { | 
					
						
							|  |  |  | 		t.Errorf("got hash %q, expected %q", string(got.Address), string(want.Address)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if !bytes.Equal(got.Data, want.Data) { | 
					
						
							|  |  |  | 		t.Errorf("got data %q, expected %q", string(got.Data), string(want.Data)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if got.StoreTimestamp != want.StoreTimestamp { | 
					
						
							|  |  |  | 		t.Errorf("got store timestamp %v, expected %v", got.StoreTimestamp, want.StoreTimestamp) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if got.AccessTimestamp != want.AccessTimestamp { | 
					
						
							|  |  |  | 		t.Errorf("got access timestamp %v, expected %v", got.AccessTimestamp, want.AccessTimestamp) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |