github.com/safing/portbase@v0.19.5/database/storage/bbolt/bbolt_test.go (about) 1 package bbolt 2 3 import ( 4 "context" 5 "os" 6 "reflect" 7 "sync" 8 "testing" 9 "time" 10 11 "github.com/safing/portbase/database/query" 12 "github.com/safing/portbase/database/record" 13 "github.com/safing/portbase/database/storage" 14 ) 15 16 var ( 17 // Compile time interface checks. 18 _ storage.Interface = &BBolt{} 19 _ storage.Batcher = &BBolt{} 20 _ storage.Purger = &BBolt{} 21 ) 22 23 type TestRecord struct { //nolint:maligned 24 record.Base 25 sync.Mutex 26 S string 27 I int 28 I8 int8 29 I16 int16 30 I32 int32 31 I64 int64 32 UI uint 33 UI8 uint8 34 UI16 uint16 35 UI32 uint32 36 UI64 uint64 37 F32 float32 38 F64 float64 39 B bool 40 } 41 42 func TestBBolt(t *testing.T) { 43 t.Parallel() 44 45 testDir, err := os.MkdirTemp("", "testing-") 46 if err != nil { 47 t.Fatal(err) 48 } 49 defer func() { 50 _ = os.RemoveAll(testDir) // clean up 51 }() 52 53 // start 54 db, err := NewBBolt("test", testDir) 55 if err != nil { 56 t.Fatal(err) 57 } 58 59 a := &TestRecord{ 60 S: "banana", 61 I: 42, 62 I8: 42, 63 I16: 42, 64 I32: 42, 65 I64: 42, 66 UI: 42, 67 UI8: 42, 68 UI16: 42, 69 UI32: 42, 70 UI64: 42, 71 F32: 42.42, 72 F64: 42.42, 73 B: true, 74 } 75 a.SetMeta(&record.Meta{}) 76 a.Meta().Update() 77 a.SetKey("test:A") 78 79 // put record 80 _, err = db.Put(a) 81 if err != nil { 82 t.Fatal(err) 83 } 84 85 // get and compare 86 r1, err := db.Get("A") 87 if err != nil { 88 t.Fatal(err) 89 } 90 91 a1 := &TestRecord{} 92 err = record.Unwrap(r1, a1) 93 if err != nil { 94 t.Fatal(err) 95 } 96 97 if !reflect.DeepEqual(a, a1) { 98 t.Fatalf("mismatch, got %v", a1) 99 } 100 101 // setup query test records 102 qA := &TestRecord{} 103 qA.SetKey("test:path/to/A") 104 qA.CreateMeta() 105 qB := &TestRecord{} 106 qB.SetKey("test:path/to/B") 107 qB.CreateMeta() 108 qC := &TestRecord{} 109 qC.SetKey("test:path/to/C") 110 qC.CreateMeta() 111 qZ := &TestRecord{} 112 qZ.SetKey("test:z") 113 qZ.CreateMeta() 114 // put 115 _, err = db.Put(qA) 116 if err == nil { 117 _, err = db.Put(qB) 118 } 119 if err == nil { 120 _, err = db.Put(qC) 121 } 122 if err == nil { 123 _, err = db.Put(qZ) 124 } 125 if err != nil { 126 t.Fatal(err) 127 } 128 129 // test query 130 q := query.New("test:path/to/").MustBeValid() 131 it, err := db.Query(q, true, true) 132 if err != nil { 133 t.Fatal(err) 134 } 135 cnt := 0 136 for range it.Next { 137 cnt++ 138 } 139 if it.Err() != nil { 140 t.Fatal(it.Err()) 141 } 142 if cnt != 3 { 143 t.Fatalf("unexpected query result count: %d", cnt) 144 } 145 146 // delete 147 err = db.Delete("A") 148 if err != nil { 149 t.Fatal(err) 150 } 151 152 // check if its gone 153 _, err = db.Get("A") 154 if err == nil { 155 t.Fatal("should fail") 156 } 157 158 // maintenance 159 err = db.MaintainRecordStates(context.TODO(), time.Now(), true) 160 if err != nil { 161 t.Fatal(err) 162 } 163 164 // maintenance 165 err = db.MaintainRecordStates(context.TODO(), time.Now(), false) 166 if err != nil { 167 t.Fatal(err) 168 } 169 170 // purging 171 purger, ok := db.(storage.Purger) 172 if ok { 173 n, err := purger.Purge(context.TODO(), query.New("test:path/to/").MustBeValid(), true, true, false) 174 if err != nil { 175 t.Fatal(err) 176 } 177 if n != 3 { 178 t.Fatalf("unexpected purge delete count: %d", n) 179 } 180 } else { 181 t.Fatal("should implement Purger") 182 } 183 184 // test query 185 q = query.New("test").MustBeValid() 186 it, err = db.Query(q, true, true) 187 if err != nil { 188 t.Fatal(err) 189 } 190 cnt = 0 191 for range it.Next { 192 cnt++ 193 } 194 if it.Err() != nil { 195 t.Fatal(it.Err()) 196 } 197 if cnt != 1 { 198 t.Fatalf("unexpected query result count: %d", cnt) 199 } 200 201 // shutdown 202 err = db.Shutdown() 203 if err != nil { 204 t.Fatal(err) 205 } 206 }