1 // Copyright 2017 syzkaller project authors. All rights reserved. 2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4 package db 5 6 import ( 7 "fmt" 8 "math/rand" 9 "os" 10 "reflect" 11 "testing" 12 13 "github.com/google/syzkaller/pkg/osutil" 14 ) 15 16 func TestBasic(t *testing.T) { 17 fn := tempFile(t) 18 defer os.Remove(fn) 19 db, err := Open(fn) 20 if err != nil { 21 t.Fatalf("failed to open db: %v", err) 22 } 23 if len(db.Records) != 0 { 24 t.Fatalf("empty db contains records") 25 } 26 db.Save("", nil, 0) 27 db.Save("1", []byte("ab"), 1) 28 db.Save("23", []byte("abcd"), 2) 29 30 want := map[string]Record{ 31 "": {Val: nil, Seq: 0}, 32 "1": {Val: []byte("ab"), Seq: 1}, 33 "23": {Val: []byte("abcd"), Seq: 2}, 34 } 35 if !reflect.DeepEqual(db.Records, want) { 36 t.Fatalf("bad db after save: %v, want: %v", db.Records, want) 37 } 38 if err := db.Flush(); err != nil { 39 t.Fatalf("failed to flush db: %v", err) 40 } 41 if !reflect.DeepEqual(db.Records, want) { 42 t.Fatalf("bad db after flush: %v, want: %v", db.Records, want) 43 } 44 db, err = Open(fn) 45 if err != nil { 46 t.Fatalf("failed to open db: %v", err) 47 } 48 if !reflect.DeepEqual(db.Records, want) { 49 t.Fatalf("bad db after reopen: %v, want: %v", db.Records, want) 50 } 51 } 52 53 func TestModify(t *testing.T) { 54 fn := tempFile(t) 55 defer os.Remove(fn) 56 db, err := Open(fn) 57 if err != nil { 58 t.Fatalf("failed to open db: %v", err) 59 } 60 db.Save("1", []byte("ab"), 0) 61 db.Save("23", nil, 1) 62 db.Save("456", []byte("abcd"), 1) 63 db.Save("7890", []byte("a"), 0) 64 db.Delete("23") 65 db.Save("1", nil, 5) 66 db.Save("456", []byte("ef"), 6) 67 db.Delete("7890") 68 db.Save("456", []byte("efg"), 0) 69 db.Save("7890", []byte("bc"), 0) 70 71 want := map[string]Record{ 72 "1": {Val: nil, Seq: 5}, 73 "456": {Val: []byte("efg"), Seq: 0}, 74 "7890": {Val: []byte("bc"), Seq: 0}, 75 } 76 if !reflect.DeepEqual(db.Records, want) { 77 t.Fatalf("bad db after modification: %v, want: %v", db.Records, want) 78 } 79 if err := db.Flush(); err != nil { 80 t.Fatalf("failed to flush db: %v", err) 81 } 82 if !reflect.DeepEqual(db.Records, want) { 83 t.Fatalf("bad db after flush: %v, want: %v", db.Records, want) 84 } 85 db, err = Open(fn) 86 if err != nil { 87 t.Fatalf("failed to open db: %v", err) 88 } 89 if !reflect.DeepEqual(db.Records, want) { 90 t.Fatalf("bad db after reopen: %v, want: %v", db.Records, want) 91 } 92 } 93 94 func TestLarge(t *testing.T) { 95 fn := tempFile(t) 96 defer os.Remove(fn) 97 db, err := Open(fn) 98 if err != nil { 99 t.Fatalf("failed to open db: %v", err) 100 } 101 const nrec = 1000 102 val := make([]byte, 1000) 103 for i := range val { 104 val[i] = byte(rand.Intn(256)) 105 } 106 for i := 0; i < nrec; i++ { 107 db.Save(fmt.Sprintf("%v", i), val, 0) 108 } 109 if err := db.Flush(); err != nil { 110 t.Fatalf("failed to flush db: %v", err) 111 } 112 db, err = Open(fn) 113 if err != nil { 114 t.Fatalf("failed to open db: %v", err) 115 } 116 if len(db.Records) != nrec { 117 t.Fatalf("wrong record count: %v, want %v", len(db.Records), nrec) 118 } 119 } 120 121 func tempFile(t *testing.T) string { 122 fn, err := osutil.TempFile("syzkaller.test.db") 123 if err != nil { 124 t.Fatal(err) 125 } 126 return fn 127 } 128