github.com/turingchain2020/turingchain@v1.1.21/common/db/table/table_test.go (about) 1 // Copyright Turing Corp. 2018 All Rights Reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 package table 5 6 import ( 7 "bytes" 8 "testing" 9 10 "github.com/turingchain2020/turingchain/common/db" 11 "github.com/turingchain2020/turingchain/types" 12 "github.com/turingchain2020/turingchain/util" 13 "github.com/golang/protobuf/proto" 14 "github.com/stretchr/testify/assert" 15 ) 16 17 func TestTransactinList(t *testing.T) { 18 dir, ldb, kvdb := util.CreateTestDB() 19 defer util.CloseTestDB(dir, ldb) 20 opt := &Option{ 21 Prefix: "prefix", 22 Name: "name", 23 Primary: "Hash", 24 Index: []string{"From", "To"}, 25 } 26 cfg := types.NewTuringchainConfig(types.GetDefaultCfgstring()) 27 table, err := NewTable(NewTransactionRow(), kvdb, opt) 28 assert.Nil(t, err) 29 addr1, priv := util.Genaddress() 30 tx1 := util.CreateNoneTx(cfg, priv) 31 err = table.Add(tx1) 32 assert.Nil(t, err) 33 tx2 := util.CreateNoneTx(cfg, priv) 34 err = table.Add(tx2) 35 assert.Nil(t, err) 36 37 addr2, priv := util.Genaddress() 38 tx3 := util.CreateNoneTx(cfg, priv) 39 err = table.Add(tx3) 40 assert.Nil(t, err) 41 tx4 := util.CreateNoneTx(cfg, priv) 42 err = table.Add(tx4) 43 assert.Nil(t, err) 44 //添加一个无效的类型 45 err = table.Add(nil) 46 assert.Equal(t, types.ErrTypeAsset, err) 47 kvs, err := table.Save() 48 assert.Nil(t, err) 49 assert.Equal(t, len(kvs), 12) 50 //save to database 51 util.SaveKVList(ldb, kvs) 52 //测试查询 53 query := table.GetQuery(kvdb) 54 55 rows, err := query.ListIndex("From", []byte(addr1), nil, 0, 0) 56 assert.Nil(t, err) 57 assert.Equal(t, 2, len(rows)) 58 if bytes.Compare(tx1.Hash(), tx2.Hash()) > 0 { 59 assert.Equal(t, true, proto.Equal(tx1, rows[0].Data)) 60 assert.Equal(t, true, proto.Equal(tx2, rows[1].Data)) 61 } else { 62 assert.Equal(t, true, proto.Equal(tx1, rows[1].Data)) 63 assert.Equal(t, true, proto.Equal(tx2, rows[0].Data)) 64 } 65 //prefix full 66 rows, err = query.ListIndex("From", []byte(addr2), nil, 0, 0) 67 assert.Nil(t, err) 68 assert.Equal(t, 2, len(rows)) 69 if bytes.Compare(tx3.Hash(), tx4.Hash()) > 0 { 70 assert.Equal(t, true, proto.Equal(tx3, rows[0].Data)) 71 assert.Equal(t, true, proto.Equal(tx4, rows[1].Data)) 72 } else { 73 assert.Equal(t, true, proto.Equal(tx3, rows[1].Data)) 74 assert.Equal(t, true, proto.Equal(tx4, rows[0].Data)) 75 } 76 //prefix part 77 rows, err = query.ListIndex("From", []byte(addr2[0:10]), nil, 0, 0) 78 assert.Nil(t, err) 79 assert.Equal(t, 2, len(rows)) 80 if bytes.Compare(tx3.Hash(), tx4.Hash()) > 0 { 81 assert.Equal(t, true, proto.Equal(tx3, rows[0].Data)) 82 assert.Equal(t, true, proto.Equal(tx4, rows[1].Data)) 83 } else { 84 assert.Equal(t, true, proto.Equal(tx3, rows[1].Data)) 85 assert.Equal(t, true, proto.Equal(tx4, rows[0].Data)) 86 } 87 //count 88 rows, err = query.ListIndex("From", []byte(addr2[0:10]), nil, 1, 0) 89 assert.Nil(t, err) 90 assert.Equal(t, 1, len(rows)) 91 if bytes.Compare(tx3.Hash(), tx4.Hash()) > 0 { 92 assert.Equal(t, true, proto.Equal(tx3, rows[0].Data)) 93 } else { 94 assert.Equal(t, true, proto.Equal(tx4, rows[0].Data)) 95 } 96 primary := rows[0].Primary 97 //primary 98 rows, err = query.ListIndex("From", nil, primary, 1, 0) 99 assert.Nil(t, err) 100 assert.Equal(t, 1, len(rows)) 101 if bytes.Compare(tx3.Hash(), tx4.Hash()) > 0 { 102 assert.Equal(t, true, proto.Equal(tx4, rows[0].Data)) 103 } else { 104 assert.Equal(t, true, proto.Equal(tx3, rows[0].Data)) 105 } 106 //prefix + primary 107 rows, err = query.ListIndex("From", []byte(addr2[0:10]), primary, 0, 0) 108 assert.Nil(t, err) 109 assert.Equal(t, 1, len(rows)) 110 if bytes.Compare(tx3.Hash(), tx4.Hash()) > 0 { 111 assert.Equal(t, true, proto.Equal(tx4, rows[0].Data)) 112 } else { 113 assert.Equal(t, true, proto.Equal(tx3, rows[0].Data)) 114 } 115 //List data 116 rows, err = query.List("From", tx3, primary, 0, 0) 117 assert.Nil(t, err) 118 assert.Equal(t, 1, len(rows)) 119 if bytes.Compare(tx3.Hash(), tx4.Hash()) > 0 { 120 assert.Equal(t, true, proto.Equal(tx4, rows[0].Data)) 121 } else { 122 assert.Equal(t, true, proto.Equal(tx3, rows[0].Data)) 123 } 124 125 rows, err = query.ListIndex("From", []byte(addr1[0:10]), primary, 0, 0) 126 assert.Equal(t, types.ErrNotFound, err) 127 assert.Equal(t, 0, len(rows)) 128 //ListPrimary all 129 rows, err = query.ListIndex("primary", nil, nil, 0, 0) 130 assert.Nil(t, err) 131 assert.Equal(t, 4, len(rows)) 132 133 //ListPrimary all 134 rows, err = query.List("primary", nil, nil, 0, 0) 135 assert.Nil(t, err) 136 assert.Equal(t, 4, len(rows)) 137 138 row, err := query.ListOne("primary", nil, nil) 139 assert.Nil(t, err) 140 assert.Equal(t, row, rows[0]) 141 142 primary = rows[0].Primary 143 rows, err = query.ListIndex("auto", primary, nil, 0, 0) 144 assert.Nil(t, err) 145 assert.Equal(t, 1, len(rows)) 146 147 rows, err = query.List("", rows[0].Data, nil, 0, 0) 148 assert.Nil(t, err) 149 assert.Equal(t, 1, len(rows)) 150 151 rows, err = query.ListIndex("", nil, primary, 0, 0) 152 assert.Nil(t, err) 153 assert.Equal(t, 3, len(rows)) 154 } 155 156 func TestTransactinListAuto(t *testing.T) { 157 dir, ldb, kvdb := util.CreateTestDB() 158 defer util.CloseTestDB(dir, ldb) 159 opt := &Option{ 160 Prefix: "prefix", 161 Name: "name", 162 Primary: "", 163 Index: []string{"From", "To"}, 164 } 165 cfg := types.NewTuringchainConfig(types.GetDefaultCfgstring()) 166 table, err := NewTable(NewTransactionRow(), kvdb, opt) 167 assert.Nil(t, err) 168 addr1, priv := util.Genaddress() 169 tx1 := util.CreateNoneTx(cfg, priv) 170 err = table.Add(tx1) 171 assert.Nil(t, err) 172 tx2 := util.CreateNoneTx(cfg, priv) 173 err = table.Add(tx2) 174 assert.Nil(t, err) 175 176 addr2, priv := util.Genaddress() 177 tx3 := util.CreateNoneTx(cfg, priv) 178 err = table.Add(tx3) 179 assert.Nil(t, err) 180 tx4 := util.CreateNoneTx(cfg, priv) 181 err = table.Add(tx4) 182 assert.Nil(t, err) 183 //添加一个无效的类型 184 err = table.Add(nil) 185 assert.Equal(t, types.ErrTypeAsset, err) 186 kvs, err := table.Save() 187 assert.Nil(t, err) 188 assert.Equal(t, len(kvs), 13) 189 //save to database 190 util.SaveKVList(ldb, kvs) 191 //测试查询 192 query := table.GetQuery(kvdb) 193 194 rows, err := query.ListIndex("From", []byte(addr1), nil, 0, db.ListASC) 195 assert.Nil(t, err) 196 assert.Equal(t, 2, len(rows)) 197 assert.Equal(t, true, proto.Equal(tx1, rows[0].Data)) 198 assert.Equal(t, true, proto.Equal(tx2, rows[1].Data)) 199 //prefix full 200 rows, err = query.ListIndex("From", []byte(addr2), nil, 0, db.ListASC) 201 assert.Nil(t, err) 202 assert.Equal(t, 2, len(rows)) 203 assert.Equal(t, true, proto.Equal(tx3, rows[0].Data)) 204 assert.Equal(t, true, proto.Equal(tx4, rows[1].Data)) 205 //prefix part 206 rows, err = query.ListIndex("From", []byte(addr2[0:10]), nil, 0, db.ListASC) 207 assert.Nil(t, err) 208 assert.Equal(t, 2, len(rows)) 209 assert.Equal(t, true, proto.Equal(tx3, rows[0].Data)) 210 assert.Equal(t, true, proto.Equal(tx4, rows[1].Data)) 211 //count 212 rows, err = query.ListIndex("From", []byte(addr2[0:10]), nil, 1, db.ListASC) 213 assert.Nil(t, err) 214 assert.Equal(t, 1, len(rows)) 215 assert.Equal(t, true, proto.Equal(tx3, rows[0].Data)) 216 primary := rows[0].Primary 217 //primary 218 rows, err = query.ListIndex("From", nil, primary, 1, db.ListASC) 219 assert.Nil(t, err) 220 assert.Equal(t, 1, len(rows)) 221 assert.Equal(t, true, proto.Equal(tx4, rows[0].Data)) 222 //prefix + primary 223 rows, err = query.ListIndex("From", []byte(addr2[0:10]), primary, 0, db.ListASC) 224 assert.Nil(t, err) 225 assert.Equal(t, 1, len(rows)) 226 assert.Equal(t, true, proto.Equal(tx4, rows[0].Data)) 227 rows, err = query.ListIndex("From", []byte(addr1[0:10]), primary, 0, db.ListASC) 228 assert.Equal(t, types.ErrNotFound, err) 229 assert.Equal(t, 0, len(rows)) 230 //ListPrimary all 231 rows, err = query.ListIndex("", nil, nil, 0, db.ListASC) 232 assert.Nil(t, err) 233 assert.Equal(t, 4, len(rows)) 234 235 primary = rows[0].Primary 236 rows, err = query.ListIndex("", primary, nil, 0, db.ListASC) 237 assert.Nil(t, err) 238 assert.Equal(t, 1, len(rows)) 239 240 rows, err = query.ListIndex("", nil, primary, 0, db.ListASC) 241 assert.Nil(t, err) 242 assert.Equal(t, 3, len(rows)) 243 } 244 245 func TestRow(t *testing.T) { 246 cfg := types.NewTuringchainConfig(types.GetDefaultCfgstring()) 247 rowmeta := NewTransactionRow() 248 row := rowmeta.CreateRow() 249 _, priv := util.Genaddress() 250 tx1 := util.CreateNoneTx(cfg, priv) 251 row.Data = tx1 252 row.Primary = tx1.Hash() 253 data, err := row.Encode() 254 assert.Nil(t, err) 255 primary, protodata, err := DecodeRow(data) 256 assert.Nil(t, err) 257 assert.Equal(t, primary, row.Primary) 258 var tx types.Transaction 259 err = types.Decode(protodata, &tx) 260 assert.Nil(t, err) 261 assert.Equal(t, proto.Equal(&tx, tx1), true) 262 } 263 264 func TestDel(t *testing.T) { 265 dir, ldb, kvdb := util.CreateTestDB() 266 defer util.CloseTestDB(dir, ldb) 267 opt := &Option{ 268 Prefix: "prefix", 269 Name: "name", 270 Primary: "Hash", 271 Index: []string{"From", "To"}, 272 } 273 cfg := types.NewTuringchainConfig(types.GetDefaultCfgstring()) 274 table, err := NewTable(NewTransactionRow(), kvdb, opt) 275 assert.Nil(t, err) 276 addr1, priv := util.Genaddress() 277 tx1 := util.CreateNoneTx(cfg, priv) 278 err = table.Add(tx1) 279 assert.Nil(t, err) 280 281 _, priv = util.Genaddress() 282 tx2 := util.CreateNoneTx(cfg, priv) 283 err = table.Add(tx2) 284 assert.Nil(t, err) 285 286 //删除掉一个 287 err = table.Del(tx1.Hash()) 288 assert.Nil(t, err) 289 290 //save 然后从列表中读取 291 kvs, err := table.Save() 292 assert.Nil(t, err) 293 assert.Equal(t, 3, len(kvs)) 294 //save to database 295 util.SaveKVList(ldb, kvs) 296 //printKV(kvs) 297 query := table.GetQuery(kvdb) 298 rows, err := query.ListIndex("From", []byte(addr1[0:10]), nil, 0, 0) 299 assert.Equal(t, types.ErrNotFound, err) 300 assert.Equal(t, 0, len(rows)) 301 } 302 303 func TestUpdate(t *testing.T) { 304 dir, ldb, kvdb := util.CreateTestDB() 305 defer util.CloseTestDB(dir, ldb) 306 opt := &Option{ 307 Prefix: "prefix", 308 Name: "name", 309 Primary: "Hash", 310 Index: []string{"From", "To"}, 311 } 312 cfg := types.NewTuringchainConfig(types.GetDefaultCfgstring()) 313 table, err := NewTable(NewTransactionRow(), kvdb, opt) 314 assert.Nil(t, err) 315 _, priv := util.Genaddress() 316 tx1 := util.CreateNoneTx(cfg, priv) 317 err = table.Add(tx1) 318 assert.Nil(t, err) 319 320 err = table.Update([]byte("hello"), tx1) 321 assert.Equal(t, err, types.ErrInvalidParam) 322 323 tx1.Signature = nil 324 err = table.Update(tx1.Hash(), tx1) 325 assert.Nil(t, err) 326 kvs, err := table.Save() 327 assert.Nil(t, err) 328 assert.Equal(t, len(kvs), 3) 329 //save to database 330 util.SaveKVList(ldb, kvs) 331 query := table.GetQuery(kvdb) 332 rows, err := query.ListIndex("From", []byte(tx1.From()), nil, 0, 0) 333 assert.Nil(t, err) 334 assert.Equal(t, rows[0].Data.(*types.Transaction).From(), tx1.From()) 335 } 336 337 func TestReplaceTwice(t *testing.T) { 338 dir, ldb, kvdb := util.CreateTestDB() 339 defer util.CloseTestDB(dir, ldb) 340 opt := &Option{ 341 Prefix: "prefix-hello", 342 Name: "name", 343 Primary: "Hash", 344 Index: []string{"From", "To"}, 345 } 346 cfg := types.NewTuringchainConfig(types.GetDefaultCfgstring()) 347 table, err := NewTable(NewTransactionRow(), kvdb, opt) 348 assert.Nil(t, err) 349 addr1, priv := util.Genaddress() 350 tx1 := util.CreateNoneTx(cfg, priv) 351 err = table.Add(tx1) 352 assert.Nil(t, err) 353 354 //修改sign的内容不改变hash,但是会改变from 值,这个时候,应该是from 做了修改,而不是产生两条记录 355 tx2 := types.Clone(tx1).(*types.Transaction) 356 tx2.Signature.Pubkey[16] = tx2.Signature.Pubkey[16] + 1 357 assert.Equal(t, tx1.From(), addr1) 358 assert.Equal(t, tx1.Hash(), tx2.Hash()) 359 360 err = table.Replace(tx2) 361 assert.Nil(t, err) 362 363 //修改sign的内容不改变hash,但是会改变from 值,这个时候,应该是from 做了修改,而不是产生两条记录 364 tx3 := types.Clone(tx1).(*types.Transaction) 365 tx3.Signature.Pubkey[10] = tx3.Signature.Pubkey[10] + 1 366 assert.Equal(t, tx1.From(), addr1) 367 assert.Equal(t, tx1.Hash(), tx2.Hash()) 368 assert.Equal(t, tx1.Hash(), tx3.Hash()) 369 370 err = table.Replace(tx3) 371 assert.Nil(t, err) 372 //save 然后从列表中读取 373 kvs, err := table.Save() 374 assert.Nil(t, err) 375 util.SaveKVList(ldb, kvs) 376 query := table.GetQuery(kvdb) 377 _, err = query.ListIndex("From", []byte(tx2.From()), nil, 0, 0) 378 assert.Equal(t, err, types.ErrNotFound) 379 } 380 381 func TestReplace(t *testing.T) { 382 dir, ldb, kvdb := util.CreateTestDB() 383 defer util.CloseTestDB(dir, ldb) 384 opt := &Option{ 385 Prefix: "prefix-hello", 386 Name: "name", 387 Primary: "Hash", 388 Index: []string{"From", "To"}, 389 } 390 cfg := types.NewTuringchainConfig(types.GetDefaultCfgstring()) 391 table, err := NewTable(NewTransactionRow(), kvdb, opt) 392 assert.Nil(t, err) 393 addr1, priv := util.Genaddress() 394 tx1 := util.CreateNoneTx(cfg, priv) 395 err = table.Add(tx1) 396 assert.Nil(t, err) 397 398 err = table.Add(tx1) 399 assert.Equal(t, err, ErrDupPrimaryKey) 400 401 //不改变hash,改变签名 402 tx2 := *tx1 403 tx2.Signature = nil 404 err = table.Replace(&tx2) 405 assert.Nil(t, err) 406 //save 然后从列表中读取 407 kvs, err := table.Save() 408 assert.Nil(t, err) 409 assert.Equal(t, 3, len(kvs)) 410 //save to database 411 util.SaveKVList(ldb, kvs) 412 query := table.GetQuery(kvdb) 413 _, err = query.ListIndex("From", []byte(addr1[0:10]), nil, 0, 0) 414 assert.Equal(t, err, types.ErrNotFound) 415 416 rows, err := query.ListIndex("From", []byte(tx2.From()), nil, 0, 0) 417 assert.Nil(t, err) 418 assert.Equal(t, rows[0].Data.(*types.Transaction).From(), tx2.From()) 419 } 420 421 type TransactionRow struct { 422 *types.Transaction 423 } 424 425 func NewTransactionRow() *TransactionRow { 426 return &TransactionRow{Transaction: &types.Transaction{}} 427 } 428 429 func (tx *TransactionRow) CreateRow() *Row { 430 return &Row{Data: &types.Transaction{}} 431 } 432 433 func (tx *TransactionRow) SetPayload(data types.Message) error { 434 if txdata, ok := data.(*types.Transaction); ok { 435 tx.Transaction = txdata 436 return nil 437 } 438 return types.ErrTypeAsset 439 } 440 441 func (tx *TransactionRow) Get(key string) ([]byte, error) { 442 if key == "Hash" { 443 return tx.Hash(), nil 444 } else if key == "From" { 445 return []byte(tx.From()), nil 446 } else if key == "To" { 447 return []byte(tx.To), nil 448 } 449 return nil, types.ErrNotFound 450 }