package dbmeta_test import ( "context" "log" "os" "reflect" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "git.bit5.ru/backend/dbmeta" "git.bit5.ru/backend/db" "git.bit5.ru/backend/meta" "github.com/go-logr/stdr" ) var logger = stdr.New(log.New(os.Stdout, "", log.Lshortfile)) //TODO create the tables below before tests //CREATE TABLE `player` ( // `id` int unsigned NOT NULL, // `client_version` char(16) NOT NULL DEFAULT '', // `reg_time` int unsigned NOT NULL DEFAULT '0', // `name` varchar(255) NOT NULL DEFAULT '', // `utc_delta` tinyint(1) NOT NULL DEFAULT '0', // PRIMARY KEY (`id`) //) ENGINE=InnoDB DEFAULT // // CREATE TABLE `item` ( // `player_id` int unsigned NOT NULL DEFAULT '0', // `id` int unsigned NOT NULL DEFAULT '0', // `proto_id` int unsigned NOT NULL DEFAULT '0', // `amount` bigint NOT NULL DEFAULT '0', // PRIMARY KEY (`player_id`,`id`), // KEY `proto_id` (`proto_id`) //) ENGINE=InnoDB DEFAULT func getDBC() *db.DBC { s := db.Settings{Host: "127.0.0.1", Port: "3306", User: "root", Pass: "test", Name: "tests_shard_1", Prefix: "tests"} dbc := db.GetDBC(db.OpenPool(s), logger) return dbc } func cleanStorage(db *db.DBC) { var tables []string db.SelectBySQL("SHOW TABLES").LoadValues(&tables) for _, t := range tables { _, err := db.DeleteFrom(t).Exec() if err != nil { panic(err) } } } func TestSaveRow(t *testing.T) { ctx := context.TODO() conn := getDBC() cleanStorage(conn) //DataPlayer index //id 0 //client_version 1 //reg_time 2 //utc_delta 3 player := &DataPlayer{Id: 100, Client_version: "0.0.1", Reg_time: 100, Utc_delta: 1} player.SetFieldChanged(0) player.SetFieldChanged(2) require.NoError(t, dbmeta.SaveRow(ctx, conn, player)) var item DataPlayer require.NoError(t, dbmeta.LoadMetaStruct(conn, &item, player.Id)) assert.EqualValues(t, "", item.Client_version) assert.EqualValues(t, 0, item.Utc_delta) assert.EqualValues(t, 100, item.Reg_time) } func TestSaveItemCollectionWithMask(t *testing.T) { ctx := context.TODO() conn := getDBC() cleanStorage(conn) ownerId := uint32(1) //DataItem index //id 0 //player_id 1 //proto_id 2 //amount 3 item1 := &DataItem{Player_id: ownerId, Id: 10, Proto_id: 100, Amount: 1} item1.SetFieldChanged(0) item1.SetFieldChanged(1) item1.SetFieldChanged(2) item2 := &DataItem{Player_id: ownerId, Id: 11, Proto_id: 200, Amount: 2} item2.SetFieldChanged(0) item2.SetFieldChanged(1) item2.SetFieldChanged(3) var items []*DataItem items = append(items, item1) items = append(items, item2) require.NoError(t, dbmeta.SaveMetaCollection(ctx, conn, reflect.ValueOf(items), ownerId, nil, false)) items = nil require.NoError(t, dbmeta.LoadMetaMStruct(conn, &items, ownerId)) assert.EqualValues(t, items[0].Player_id, ownerId) assert.EqualValues(t, items[0].Id, 10) assert.EqualValues(t, items[0].Proto_id, 100) assert.EqualValues(t, items[0].Amount, 0) assert.EqualValues(t, items[1].Player_id, ownerId) assert.EqualValues(t, items[1].Id, 11) assert.EqualValues(t, items[1].Proto_id, 0) assert.EqualValues(t, items[1].Amount, 2) } func TestSaveItemCollectionWithoutMask(t *testing.T) { ctx := context.TODO() conn := getDBC() cleanStorage(conn) ownerId := uint32(1) item1 := &DataItem{Player_id: ownerId, Id: 10, Proto_id: 100, Amount: 1} item2 := &DataItem{Player_id: ownerId, Id: 11, Proto_id: 200, Amount: 2} var items []*DataItem items = append(items, item1) items = append(items, item2) require.NoError(t, dbmeta.SaveMetaCollection(ctx, conn, reflect.ValueOf(items), ownerId, nil, false)) items = nil require.NoError(t, dbmeta.LoadMetaMStruct(conn, &items, ownerId)) assert.EqualValues(t, items[0].Player_id, ownerId) assert.EqualValues(t, items[0].Id, 10) assert.EqualValues(t, items[0].Proto_id, 100) assert.EqualValues(t, items[0].Amount, 1) assert.EqualValues(t, items[1].Player_id, ownerId) assert.EqualValues(t, items[1].Id, 11) assert.EqualValues(t, items[1].Proto_id, 200) assert.EqualValues(t, items[1].Amount, 2) } func TestRemoveIds(t *testing.T) { ids := &dbmeta.RemovedIds{} assert.EqualValues(t, []uint64{}, ids.GetList(100)) ids.Add(100, 1) ids.Add(100, 3) ids.Add(200, 1) ids.Add(300, 3) assert.EqualValues(t, false, ids.HasList(10)) assert.EqualValues(t, true, ids.HasList(100)) assert.EqualValues(t, true, ids.HasList(300)) assert.EqualValues(t, []uint64{1, 3}, ids.GetList(100)) assert.EqualValues(t, []uint64{3}, ids.GetList(300)) } /////////////////////////////////////////////////////////////////////////////// type DataPlayer struct { Id uint32 `json:"id" db:"id"` Client_version string `json:"client_version" db:"client_version"` Reg_time uint32 `json:"reg_time" db:"reg_time"` Name string `json:"name" db:"name"` Utc_delta int32 `json:"utc_delta" db:"utc_delta"` fieldsMask meta.FieldsMask } var _DataPlayer_class_props map[string]string = map[string]string{"POD": "","bitfields": "","pkey": "id","table": "player","owner": "id","id": "id","cloneable": "",} var _DataPlayer_class_fields []string = []string{"id","client_version","reg_time","name","utc_delta"} var _DataPlayer_fields_props meta.ClassFieldsProps = map[string]map[string]string{"Id" : map[string]string{"optional": "1",},"Client_version" : map[string]string{"strmax": "16","optional": "1",},"Reg_time" : map[string]string{"default": "","optional": "1",},"Name" : map[string]string{"default": "\"\"","optional": "1",},"Utc_delta" : map[string]string{"default": "","optional": "1",}} func DataPlayer_CLASS_ID() uint32 { return 74407040 } type IDataPlayer interface { meta.IMetaStruct PtrDataPlayer() *DataPlayer } func (*DataPlayer) CLASS_ID() uint32 { return 74407040 } func (*DataPlayer) CLASS_NAME() string { return "DataPlayer" } func (*DataPlayer) CLASS_PROPS() *map[string]string { return &_DataPlayer_class_props } func (*DataPlayer) CLASS_FIELDS() []string { return _DataPlayer_class_fields } func (*DataPlayer) CLASS_FIELDS_PROPS() *meta.ClassFieldsProps { return &_DataPlayer_fields_props } //convenience getter func PtrDataPlayer(m meta.IMetaStruct) *DataPlayer { p, ok := m.(IDataPlayer) if !ok { return nil } return p.PtrDataPlayer() } func (self *DataPlayer) PtrDataPlayer() *DataPlayer { return self } func NewDataPlayer() *DataPlayer { item := new (DataPlayer) item.Reset() return item } func (self *DataPlayer) Reset() { self.Id = 0 self.Client_version = "" self.Reg_time = 0 self.Name = "" self.Utc_delta = 0 self.fieldsMask = meta.FieldsMask{} } func (self *DataPlayer) Read(reader meta.Reader) error { return meta.ReadStruct(reader, self, "") } func (self *DataPlayer) ReadFields(reader meta.Reader) error { self.Reset() use_mask, mask, err := reader.TryReadMask() if err != nil { return err } self.fieldsMask = mask _cont_size, err := reader.GetContainerSize() if err != nil { return err } if _cont_size < 0 { _cont_size = 0 } if _cont_size <= 0 { return nil } if !use_mask { _cont_size-- } if !use_mask || (use_mask && self.HasValue(0)) { if err := reader.ReadU32(&self.Id, "id"); err != nil { return /*optional*/nil } } if _cont_size <= 0 { return nil } if !use_mask { _cont_size-- } if !use_mask || (use_mask && self.HasValue(1)) { if err := reader.ReadString(&self.Client_version, "client_version"); err != nil { return /*optional*/nil } } if _cont_size <= 0 { return nil } if !use_mask { _cont_size-- } if !use_mask || (use_mask && self.HasValue(2)) { if err := reader.ReadU32(&self.Reg_time, "reg_time"); err != nil { return /*optional*/nil } } if _cont_size <= 0 { return nil } if !use_mask { _cont_size-- } if !use_mask || (use_mask && self.HasValue(3)) { if err := reader.ReadString(&self.Name, "name"); err != nil { return /*optional*/nil } } if _cont_size <= 0 { return nil } if !use_mask { _cont_size-- } if !use_mask || (use_mask && self.HasValue(4)) { if err := reader.ReadI32(&self.Utc_delta, "utc_delta"); err != nil { return /*optional*/nil } } return nil } func (self *DataPlayer) Write(writer meta.Writer) error { return meta.WriteStruct(writer, self, "") } func (self *DataPlayer) WriteFields(writer meta.Writer) error { if err := writer.WriteU32(self.Id, "id"); err != nil { return err } if err := writer.WriteString(self.Client_version, "client_version"); err != nil { return err } if err := writer.WriteU32(self.Reg_time, "reg_time"); err != nil { return err } if err := writer.WriteString(self.Name, "name"); err != nil { return err } if err := writer.WriteI32(self.Utc_delta, "utc_delta"); err != nil { return err } return nil } func(self *DataPlayer) HasValue(index uint64) bool { return self.fieldsMask.FieldChanged(index) } func(self *DataPlayer) SetFieldChanged(index uint64) { self.fieldsMask.SetFieldChanged(index) } func(self *DataPlayer) IsMaskFilled() bool { return self.fieldsMask.IsFilled() } func(self *DataPlayer) GetMask() meta.FieldsMask { return self.fieldsMask } type DataItem struct { Id uint32 `json:"id" db:"id"` Player_id uint32 `json:"player_id" db:"player_id"` Proto_id uint32 `json:"proto_id" db:"proto_id"` Amount int64 `json:"amount" db:"amount"` fieldsMask meta.FieldsMask } var _DataItem_class_props map[string]string = map[string]string{"POD": "","table": "item","id": "id","owner": "player_id","bitfields": "",} var _DataItem_class_fields []string = []string{"id","player_id","proto_id","amount",} var _DataItem_fields_props meta.ClassFieldsProps = map[string]map[string]string{"Id" : map[string]string{"optional": "1",},"Player_id" : map[string]string{"optional": "1",},"Proto_id" : map[string]string{"obscured": "","optional": "1",},"Amount" : map[string]string{"obscured": "","optional": "1",},} func DataItem_CLASS_ID() uint32 { return 263721017 } type IDataItem interface { meta.IMetaStruct PtrDataItem() *DataItem } func (*DataItem) CLASS_ID() uint32 { return 263721017 } func (*DataItem) CLASS_NAME() string { return "DataItem" } func (*DataItem) CLASS_PROPS() *map[string]string { return &_DataItem_class_props } func (*DataItem) CLASS_FIELDS() []string { return _DataItem_class_fields } func (*DataItem) CLASS_FIELDS_PROPS() *meta.ClassFieldsProps { return &_DataItem_fields_props } //convenience getter func PtrDataItem(m meta.IMetaStruct) *DataItem { p, ok := m.(IDataItem) if !ok { return nil } return p.PtrDataItem() } func (self *DataItem) PtrDataItem() *DataItem { return self } func NewDataItem() *DataItem { item := new (DataItem) item.Reset() return item } func (self *DataItem) Reset() { self.Id = 0 self.Player_id = 0 self.Proto_id = 0 self.Amount = 0 self.fieldsMask = meta.FieldsMask{} } func (self *DataItem) Read(reader meta.Reader) error { return meta.ReadStruct(reader, self, "") } func (self *DataItem) ReadFields(reader meta.Reader) error { self.Reset() use_mask, mask, err := reader.TryReadMask() if err != nil { return err } self.fieldsMask = mask _cont_size, err := reader.GetContainerSize() if err != nil { return err } if _cont_size < 0 { _cont_size = 0 } if _cont_size <= 0 { return nil } if !use_mask { _cont_size-- } if !use_mask || (use_mask && self.HasValue(0)) { if err := reader.ReadU32(&self.Id, "id"); err != nil { return /*optional*/nil } } if _cont_size <= 0 { return nil } if !use_mask { _cont_size-- } if !use_mask || (use_mask && self.HasValue(1)) { if err := reader.ReadU32(&self.Player_id, "player_id"); err != nil { return /*optional*/nil } } if _cont_size <= 0 { return nil } if !use_mask { _cont_size-- } if !use_mask || (use_mask && self.HasValue(2)) { if err := reader.ReadU32(&self.Proto_id, "proto_id"); err != nil { return /*optional*/nil } } if _cont_size <= 0 { return nil } if !use_mask { _cont_size-- } if !use_mask || (use_mask && self.HasValue(3)) { if err := reader.ReadI64(&self.Amount, "amount"); err != nil { return /*optional*/nil } } return nil } func (self *DataItem) Write(writer meta.Writer) error { return meta.WriteStruct(writer, self, "") } func (self *DataItem) WriteFields(writer meta.Writer) error { if err := writer.WriteU32(self.Id, "id"); err != nil { return err } if err := writer.WriteU32(self.Player_id, "player_id"); err != nil { return err } if err := writer.WriteU32(self.Proto_id, "proto_id"); err != nil { return err } if err := writer.WriteI64(self.Amount, "amount"); err != nil { return err } return nil } func(self *DataItem) HasValue(index uint64) bool { return self.fieldsMask.FieldChanged(index) } func(self *DataItem) SetFieldChanged(index uint64) { self.fieldsMask.SetFieldChanged(index) } func(self *DataItem) IsMaskFilled() bool { return self.fieldsMask.IsFilled() } func(self *DataItem) GetMask() meta.FieldsMask { return self.fieldsMask } func (self *DataItem) NewInstance() meta.IMetaDataItem { return NewDataItem() } func (self *DataItem) GetDbTableName() string { return "item" } func (self *DataItem) GetDbFields() []string { return self.CLASS_FIELDS() } func (self *DataItem) GetOwnerFieldName() string { return "player_id" } func (self *DataItem) GetIdFieldName() string { return "id" } func (self *DataItem) GetIdValue() uint64 { return uint64(self.Id) } func (self *DataItem) Import(data interface{}) { switch data.(type) { case DataItem: { row := data.(DataItem) self.Id = row.Id self.Player_id = row.Player_id self.Proto_id = row.Proto_id self.Amount = row.Amount break } default: break } } func (self *DataItem) Export(data []interface{}) { data[0] = self.Id data[1] = self.Player_id data[2] = self.Proto_id data[3] = self.Amount }