123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- /*
- * EliasDB
- *
- * Copyright 2016 Matthias Ladkau. All rights reserved.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
- package hash
- import (
- "fmt"
- "testing"
- "devt.de/krotik/eliasdb/storage"
- "devt.de/krotik/eliasdb/storage/file"
- )
- func TestIterator(t *testing.T) {
- // Do a very simple case
- sm := storage.NewMemoryStorageManager("testsm")
- htree, _ := NewHTree(sm)
- page := htree.Root
- if loc := page.Location(); loc != 1 {
- t.Error("Unexpected root location:", loc)
- return
- }
- // Fill up the tree
- page.Put([]byte("testkey1"), "test1")
- page.Put([]byte("testkey8"), "test8")
- page.Put([]byte("testkey5"), "test5")
- it := NewHTreeIterator(htree)
- if k, v := it.Next(); string(k) != "testkey1" || v != "test1" {
- t.Error("Unexpected next result:", k, v)
- return
- }
- if k, v := it.Next(); string(k) != "testkey8" || v != "test8" {
- t.Error("Unexpected next result:", k, v)
- return
- }
- if k, v := it.Next(); string(k) != "testkey5" || v != "test5" {
- t.Error("Unexpected next result:", k, v)
- return
- }
- if it.HasNext() {
- t.Error("Iterator should be finished")
- return
- }
- if k, v := it.Next(); k != nil || v != nil {
- t.Error("Return values should be nil")
- return
- }
- // Create a new iterator and try the same steps again
- it = NewHTreeIterator(htree)
- if k, v := it.Next(); string(k) != "testkey1" || v != "test1" {
- t.Error("Unexpected next result:", k, v)
- return
- }
- if k, v := it.Next(); string(k) != "testkey8" || v != "test8" {
- t.Error("Unexpected next result:", k, v)
- return
- }
- // But before the iterator finishes we change the tree behind its back
- page.Put([]byte("testkey2"), "test2")
- page.Put([]byte("testkey3"), "test3")
- page.Put([]byte("testkey4"), "test4")
- page.Put([]byte("testkey6"), "test6")
- page.Put([]byte("testkey7"), "test7")
- page.Put([]byte("testkey9"), "test9")
- page.Put([]byte("testkey100"), "test100")
- page.Put([]byte("abba1"), "song1")
- page.Put([]byte("tfst"), "zzzz")
- // The tree has changed behind the iterator's back.
- if k, v := it.Next(); string(k) != "testkey5" || v != "test5" {
- t.Error("Unexpected next result:", k, v)
- return
- }
- // We get now all the items in the Children array of the root page which
- // have been inserted after the current location. The iterator then finishes
- // normally.
- if k, v := it.Next(); string(k) != "tfst" || v != "zzzz" {
- t.Error("Unexpected next result:", k, v)
- return
- }
- if it.HasNext() {
- t.Error("Iterator should be finished")
- return
- }
- if k, v := it.Next(); k != nil || v != nil {
- t.Error("Return values should be nil")
- return
- }
- // Create a new iterator and see that we can iterate everything
- it = NewHTreeIterator(htree)
- if k, v := it.Next(); string(k) != "testkey100" || v != "test100" {
- t.Error("Unexpected next result:", k, v)
- return
- }
- if k, v := it.Next(); string(k) != "abba1" || v != "song1" {
- t.Error("Unexpected next result:", k, v)
- return
- }
- if k, v := it.Next(); string(k) != "testkey1" || v != "test1" {
- t.Error("Unexpected next result:", k, v)
- return
- }
- if k, v := it.Next(); string(k) != "testkey8" || v != "test8" {
- t.Error("Unexpected next result:", k, v)
- return
- }
- if k, v := it.Next(); string(k) != "testkey5" || v != "test5" {
- t.Error("Unexpected next result:", k, v)
- return
- }
- if k, v := it.Next(); string(k) != "testkey2" || v != "test2" {
- t.Error("Unexpected next result:", k, v)
- return
- }
- if k, v := it.Next(); string(k) != "testkey3" || v != "test3" {
- t.Error("Unexpected next result:", k, v)
- return
- }
- if k, v := it.Next(); string(k) != "testkey4" || v != "test4" {
- t.Error("Unexpected next result:", k, v)
- return
- }
- if k, v := it.Next(); string(k) != "testkey6" || v != "test6" {
- t.Error("Unexpected next result:", k, v)
- return
- }
- if k, v := it.Next(); string(k) != "testkey7" || v != "test7" {
- t.Error("Unexpected next result:", k, v)
- return
- }
- if k, v := it.Next(); string(k) != "testkey9" || v != "test9" {
- t.Error("Unexpected next result:", k, v)
- return
- }
- if k, v := it.Next(); string(k) != "tfst" || v != "zzzz" {
- t.Error("Unexpected next result:", k, v)
- return
- }
- if it.HasNext() {
- t.Error("Iterator should be finished")
- return
- }
- if k, v := it.Next(); k != nil || v != nil {
- t.Error("Return values should be nil")
- return
- }
- // Test error case
- it = NewHTreeIterator(htree)
- if k, v := it.Next(); string(k) != "testkey100" || v != "test100" {
- t.Error("Unexpected next result:", k, v)
- return
- }
- sm.AccessMap[3] = storage.AccessCacheAndFetchSeriousError
- if k, v := it.Next(); string(k) != "abba1" || v != "song1" {
- t.Error("Unexpected next result:", k, v)
- return
- }
- if k, v := it.Next(); k != nil || v != nil {
- t.Error("Unexpected next result:", k, v)
- return
- }
- if it.LastError != file.ErrAlreadyInUse {
- t.Error("Unexpected last error pointer of iterator")
- return
- }
- delete(sm.AccessMap, 3)
- if fmt.Sprint(it) != "HTree Iterator (tree: 1)\n"+
- " path: []\n"+
- " indices: []\n"+
- " next: [] / <nil>\n" {
- t.Error("Unexpected tree string representation:", it)
- return
- }
- }
|