Improving tests

This commit is contained in:
Pavel Shevaev 2022-11-15 18:19:27 +03:00
parent 911cdd3019
commit fa12207e07
1 changed files with 303 additions and 270 deletions

View File

@ -10,8 +10,8 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"git.bit5.ru/backend/dbmeta"
"git.bit5.ru/backend/db" "git.bit5.ru/backend/db"
"git.bit5.ru/backend/dbmeta"
"git.bit5.ru/backend/meta" "git.bit5.ru/backend/meta"
"github.com/go-logr/stdr" "github.com/go-logr/stdr"
@ -19,47 +19,49 @@ import (
var logger = stdr.New(log.New(os.Stdout, "", log.Lshortfile)) 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 { func getDBC() *db.DBC {
s := db.Settings{Host: "127.0.0.1", Port: "3306", User: "root", Pass: "test", Name: "tests_shard_1", Prefix: "tests"} s := db.Settings{Host: "127.0.0.1", Port: "3306", User: "root", Pass: "test", Name: "tests", Prefix: "tests"}
dbc := db.GetDBC(db.OpenPool(s), logger) dbc := db.GetDBC(db.OpenPool(s), logger)
return dbc return dbc
} }
func cleanStorage(db *db.DBC) { func setupStorage(db *db.DBC) {
var tables []string
db.SelectBySQL("SHOW TABLES").LoadValues(&tables) var sqls []string
for _, t := range tables { sqls = append(sqls, "DROP TABLE IF EXISTS player")
_, err := db.DeleteFrom(t).Exec() sqls = append(sqls, `CREATE TABLE player (
if err != nil { id int unsigned NOT NULL,
panic(err) 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
`)
sqls = append(sqls, "DROP TABLE IF EXISTS item")
sqls = append(sqls, `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
`)
for _, sql := range sqls {
_, err := db.DB().Exec(sql)
if err != nil {
panic(sql)
} }
}
} }
func TestSaveRow(t *testing.T) { func TestSaveRow(t *testing.T) {
ctx := context.TODO() ctx := context.TODO()
conn := getDBC() conn := getDBC()
cleanStorage(conn) setupStorage(conn)
//DataPlayer index //DataPlayer index
//id 0 //id 0
@ -84,7 +86,7 @@ func TestSaveItemCollectionWithMask(t *testing.T) {
ctx := context.TODO() ctx := context.TODO()
conn := getDBC() conn := getDBC()
cleanStorage(conn) setupStorage(conn)
ownerId := uint32(1) ownerId := uint32(1)
@ -128,7 +130,7 @@ func TestSaveItemCollectionWithoutMask(t *testing.T) {
ctx := context.TODO() ctx := context.TODO()
conn := getDBC() conn := getDBC()
cleanStorage(conn) setupStorage(conn)
ownerId := uint32(1) ownerId := uint32(1)
@ -177,394 +179,425 @@ func TestRemoveIds(t *testing.T) {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
type DataPlayer struct { type DataPlayer struct {
Id uint32 `json:"id" db:"id"`
Id uint32 `json:"id" db:"id"` Client_version string `json:"client_version" db:"client_version"`
Client_version string `json:"client_version" db:"client_version"` Reg_time uint32 `json:"reg_time" db:"reg_time"`
Reg_time uint32 `json:"reg_time" db:"reg_time"` Name string `json:"name" db:"name"`
Name string `json:"name" db:"name"` Utc_delta int32 `json:"utc_delta" db:"utc_delta"`
Utc_delta int32 `json:"utc_delta" db:"utc_delta"` fieldsMask meta.FieldsMask
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_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_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",}} 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 { func DataPlayer_CLASS_ID() uint32 {
return 74407040 return 74407040
} }
type IDataPlayer interface { type IDataPlayer interface {
meta.IMetaStruct meta.IMetaStruct
PtrDataPlayer() *DataPlayer PtrDataPlayer() *DataPlayer
} }
func (*DataPlayer) CLASS_ID() uint32 { func (*DataPlayer) CLASS_ID() uint32 {
return 74407040 return 74407040
} }
func (*DataPlayer) CLASS_NAME() string { func (*DataPlayer) CLASS_NAME() string {
return "DataPlayer" return "DataPlayer"
} }
func (*DataPlayer) CLASS_PROPS() *map[string]string { func (*DataPlayer) CLASS_PROPS() *map[string]string {
return &_DataPlayer_class_props return &_DataPlayer_class_props
} }
func (*DataPlayer) CLASS_FIELDS() []string { func (*DataPlayer) CLASS_FIELDS() []string {
return _DataPlayer_class_fields return _DataPlayer_class_fields
} }
func (*DataPlayer) CLASS_FIELDS_PROPS() *meta.ClassFieldsProps { func (*DataPlayer) CLASS_FIELDS_PROPS() *meta.ClassFieldsProps {
return &_DataPlayer_fields_props return &_DataPlayer_fields_props
} }
//convenience getter //convenience getter
func PtrDataPlayer(m meta.IMetaStruct) *DataPlayer { func PtrDataPlayer(m meta.IMetaStruct) *DataPlayer {
p, ok := m.(IDataPlayer) p, ok := m.(IDataPlayer)
if !ok { if !ok {
return nil return nil
} }
return p.PtrDataPlayer() return p.PtrDataPlayer()
} }
func (self *DataPlayer) PtrDataPlayer() *DataPlayer { func (self *DataPlayer) PtrDataPlayer() *DataPlayer {
return self return self
} }
func NewDataPlayer() *DataPlayer { func NewDataPlayer() *DataPlayer {
item := new (DataPlayer) item := new(DataPlayer)
item.Reset() item.Reset()
return item return item
} }
func (self *DataPlayer) Reset() { func (self *DataPlayer) Reset() {
self.Id = 0 self.Id = 0
self.Client_version = "" self.Client_version = ""
self.Reg_time = 0 self.Reg_time = 0
self.Name = "" self.Name = ""
self.Utc_delta = 0 self.Utc_delta = 0
self.fieldsMask = meta.FieldsMask{} self.fieldsMask = meta.FieldsMask{}
} }
func (self *DataPlayer) Read(reader meta.Reader) error { func (self *DataPlayer) Read(reader meta.Reader) error {
return meta.ReadStruct(reader, self, "") return meta.ReadStruct(reader, self, "")
} }
func (self *DataPlayer) ReadFields(reader meta.Reader) error { func (self *DataPlayer) ReadFields(reader meta.Reader) error {
self.Reset() self.Reset()
use_mask, mask, err := reader.TryReadMask()
if err != nil { use_mask, mask, err := reader.TryReadMask()
return err if err != nil {
} return err
self.fieldsMask = mask }
_cont_size, err := reader.GetContainerSize() self.fieldsMask = mask
if err != nil {
return err _cont_size, err := reader.GetContainerSize()
} if err != nil {
if _cont_size < 0 { return err
_cont_size = 0 }
} if _cont_size < 0 {
if _cont_size <= 0 { _cont_size = 0
return nil }
} if _cont_size <= 0 {
if !use_mask { return nil
_cont_size-- }
} if !use_mask {
if !use_mask || (use_mask && self.HasValue(0)) { _cont_size--
if err := reader.ReadU32(&self.Id, "id"); err != nil { return /*optional*/nil } }
} if !use_mask || (use_mask && self.HasValue(0)) {
if _cont_size <= 0 { if err := reader.ReadU32(&self.Id, "id"); err != nil {
return nil return /*optional*/ nil
} }
if !use_mask { }
_cont_size-- if _cont_size <= 0 {
} return nil
if !use_mask || (use_mask && self.HasValue(1)) { }
if err := reader.ReadString(&self.Client_version, "client_version"); err != nil { return /*optional*/nil } if !use_mask {
} _cont_size--
if _cont_size <= 0 { }
return nil if !use_mask || (use_mask && self.HasValue(1)) {
} if err := reader.ReadString(&self.Client_version, "client_version"); err != nil {
if !use_mask { return /*optional*/ nil
_cont_size-- }
} }
if !use_mask || (use_mask && self.HasValue(2)) { if _cont_size <= 0 {
if err := reader.ReadU32(&self.Reg_time, "reg_time"); err != nil { return /*optional*/nil } return nil
} }
if _cont_size <= 0 { if !use_mask {
return nil _cont_size--
} }
if !use_mask { if !use_mask || (use_mask && self.HasValue(2)) {
_cont_size-- if err := reader.ReadU32(&self.Reg_time, "reg_time"); err != nil {
} return /*optional*/ nil
if !use_mask || (use_mask && self.HasValue(3)) { }
if err := reader.ReadString(&self.Name, "name"); err != nil { return /*optional*/nil } }
} if _cont_size <= 0 {
if _cont_size <= 0 { return nil
return nil }
} if !use_mask {
if !use_mask { _cont_size--
_cont_size-- }
} if !use_mask || (use_mask && self.HasValue(3)) {
if !use_mask || (use_mask && self.HasValue(4)) { if err := reader.ReadString(&self.Name, "name"); err != nil {
if err := reader.ReadI32(&self.Utc_delta, "utc_delta"); err != nil { return /*optional*/nil } return /*optional*/ nil
} }
return 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 { func (self *DataPlayer) Write(writer meta.Writer) error {
return meta.WriteStruct(writer, self, "") return meta.WriteStruct(writer, self, "")
} }
func (self *DataPlayer) WriteFields(writer meta.Writer) error { 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.Id, "id"); err != nil {
return err
}
if err := writer.WriteU32(self.Reg_time, "reg_time"); err != nil { return err } if err := writer.WriteString(self.Client_version, "client_version"); err != nil {
return err
}
if err := writer.WriteString(self.Name, "name"); err != nil { return err } if err := writer.WriteU32(self.Reg_time, "reg_time"); err != nil {
return err
}
if err := writer.WriteI32(self.Utc_delta, "utc_delta"); err != nil { return err } if err := writer.WriteString(self.Name, "name"); err != nil {
return err
}
return nil if err := writer.WriteI32(self.Utc_delta, "utc_delta"); err != nil {
return err
}
return nil
} }
func(self *DataPlayer) HasValue(index uint64) bool { func (self *DataPlayer) HasValue(index uint64) bool {
return self.fieldsMask.FieldChanged(index) return self.fieldsMask.FieldChanged(index)
} }
func(self *DataPlayer) SetFieldChanged(index uint64) { func (self *DataPlayer) SetFieldChanged(index uint64) {
self.fieldsMask.SetFieldChanged(index) self.fieldsMask.SetFieldChanged(index)
} }
func(self *DataPlayer) IsMaskFilled() bool { func (self *DataPlayer) IsMaskFilled() bool {
return self.fieldsMask.IsFilled() return self.fieldsMask.IsFilled()
} }
func(self *DataPlayer) GetMask() meta.FieldsMask { func (self *DataPlayer) GetMask() meta.FieldsMask {
return self.fieldsMask return self.fieldsMask
} }
type DataItem struct { type DataItem struct {
Id uint32 `json:"id" db:"id"`
Id uint32 `json:"id" db:"id"` Player_id uint32 `json:"player_id" db:"player_id"`
Player_id uint32 `json:"player_id" db:"player_id"` Proto_id uint32 `json:"proto_id" db:"proto_id"`
Proto_id uint32 `json:"proto_id" db:"proto_id"` Amount int64 `json:"amount" db:"amount"`
Amount int64 `json:"amount" db:"amount"` fieldsMask meta.FieldsMask
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_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_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",},} 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 { func DataItem_CLASS_ID() uint32 {
return 263721017 return 263721017
} }
type IDataItem interface { type IDataItem interface {
meta.IMetaStruct meta.IMetaStruct
PtrDataItem() *DataItem PtrDataItem() *DataItem
} }
func (*DataItem) CLASS_ID() uint32 { func (*DataItem) CLASS_ID() uint32 {
return 263721017 return 263721017
} }
func (*DataItem) CLASS_NAME() string { func (*DataItem) CLASS_NAME() string {
return "DataItem" return "DataItem"
} }
func (*DataItem) CLASS_PROPS() *map[string]string { func (*DataItem) CLASS_PROPS() *map[string]string {
return &_DataItem_class_props return &_DataItem_class_props
} }
func (*DataItem) CLASS_FIELDS() []string { func (*DataItem) CLASS_FIELDS() []string {
return _DataItem_class_fields return _DataItem_class_fields
} }
func (*DataItem) CLASS_FIELDS_PROPS() *meta.ClassFieldsProps { func (*DataItem) CLASS_FIELDS_PROPS() *meta.ClassFieldsProps {
return &_DataItem_fields_props return &_DataItem_fields_props
} }
//convenience getter //convenience getter
func PtrDataItem(m meta.IMetaStruct) *DataItem { func PtrDataItem(m meta.IMetaStruct) *DataItem {
p, ok := m.(IDataItem) p, ok := m.(IDataItem)
if !ok { if !ok {
return nil return nil
} }
return p.PtrDataItem() return p.PtrDataItem()
} }
func (self *DataItem) PtrDataItem() *DataItem { func (self *DataItem) PtrDataItem() *DataItem {
return self return self
} }
func NewDataItem() *DataItem { func NewDataItem() *DataItem {
item := new (DataItem) item := new(DataItem)
item.Reset() item.Reset()
return item return item
} }
func (self *DataItem) Reset() { func (self *DataItem) Reset() {
self.Id = 0 self.Id = 0
self.Player_id = 0 self.Player_id = 0
self.Proto_id = 0 self.Proto_id = 0
self.Amount = 0 self.Amount = 0
self.fieldsMask = meta.FieldsMask{} self.fieldsMask = meta.FieldsMask{}
} }
func (self *DataItem) Read(reader meta.Reader) error { func (self *DataItem) Read(reader meta.Reader) error {
return meta.ReadStruct(reader, self, "") return meta.ReadStruct(reader, self, "")
} }
func (self *DataItem) ReadFields(reader meta.Reader) error { func (self *DataItem) ReadFields(reader meta.Reader) error {
self.Reset() self.Reset()
use_mask, mask, err := reader.TryReadMask()
if err != nil { use_mask, mask, err := reader.TryReadMask()
return err if err != nil {
} return err
self.fieldsMask = mask }
_cont_size, err := reader.GetContainerSize() self.fieldsMask = mask
if err != nil {
return err _cont_size, err := reader.GetContainerSize()
} if err != nil {
if _cont_size < 0 { return err
_cont_size = 0 }
} if _cont_size < 0 {
if _cont_size <= 0 { _cont_size = 0
return nil }
} if _cont_size <= 0 {
if !use_mask { return nil
_cont_size-- }
} if !use_mask {
if !use_mask || (use_mask && self.HasValue(0)) { _cont_size--
if err := reader.ReadU32(&self.Id, "id"); err != nil { return /*optional*/nil } }
} if !use_mask || (use_mask && self.HasValue(0)) {
if _cont_size <= 0 { if err := reader.ReadU32(&self.Id, "id"); err != nil {
return nil return /*optional*/ nil
} }
if !use_mask { }
_cont_size-- if _cont_size <= 0 {
} return nil
if !use_mask || (use_mask && self.HasValue(1)) { }
if err := reader.ReadU32(&self.Player_id, "player_id"); err != nil { return /*optional*/nil } if !use_mask {
} _cont_size--
if _cont_size <= 0 { }
return nil if !use_mask || (use_mask && self.HasValue(1)) {
} if err := reader.ReadU32(&self.Player_id, "player_id"); err != nil {
if !use_mask { return /*optional*/ nil
_cont_size-- }
} }
if !use_mask || (use_mask && self.HasValue(2)) { if _cont_size <= 0 {
if err := reader.ReadU32(&self.Proto_id, "proto_id"); err != nil { return /*optional*/nil } return nil
} }
if _cont_size <= 0 { if !use_mask {
return nil _cont_size--
} }
if !use_mask { if !use_mask || (use_mask && self.HasValue(2)) {
_cont_size-- if err := reader.ReadU32(&self.Proto_id, "proto_id"); err != nil {
} return /*optional*/ nil
if !use_mask || (use_mask && self.HasValue(3)) { }
if err := reader.ReadI64(&self.Amount, "amount"); err != nil { return /*optional*/nil } }
} if _cont_size <= 0 {
return nil 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 { func (self *DataItem) Write(writer meta.Writer) error {
return meta.WriteStruct(writer, self, "") return meta.WriteStruct(writer, self, "")
} }
func (self *DataItem) WriteFields(writer meta.Writer) error { 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.Id, "id"); err != nil {
return err
}
if err := writer.WriteU32(self.Proto_id, "proto_id"); err != nil { return err } if err := writer.WriteU32(self.Player_id, "player_id"); err != nil {
return err
}
if err := writer.WriteI64(self.Amount, "amount"); err != nil { return err } if err := writer.WriteU32(self.Proto_id, "proto_id"); err != nil {
return err
}
return nil if err := writer.WriteI64(self.Amount, "amount"); err != nil {
return err
}
return nil
} }
func(self *DataItem) HasValue(index uint64) bool { func (self *DataItem) HasValue(index uint64) bool {
return self.fieldsMask.FieldChanged(index) return self.fieldsMask.FieldChanged(index)
} }
func(self *DataItem) SetFieldChanged(index uint64) { func (self *DataItem) SetFieldChanged(index uint64) {
self.fieldsMask.SetFieldChanged(index) self.fieldsMask.SetFieldChanged(index)
} }
func(self *DataItem) IsMaskFilled() bool { func (self *DataItem) IsMaskFilled() bool {
return self.fieldsMask.IsFilled() return self.fieldsMask.IsFilled()
} }
func(self *DataItem) GetMask() meta.FieldsMask { func (self *DataItem) GetMask() meta.FieldsMask {
return self.fieldsMask return self.fieldsMask
} }
func (self *DataItem) NewInstance() meta.IMetaDataItem { func (self *DataItem) NewInstance() meta.IMetaDataItem {
return NewDataItem() return NewDataItem()
} }
func (self *DataItem) GetDbTableName() string { func (self *DataItem) GetDbTableName() string {
return "item" return "item"
} }
func (self *DataItem) GetDbFields() []string { func (self *DataItem) GetDbFields() []string {
return self.CLASS_FIELDS() return self.CLASS_FIELDS()
} }
func (self *DataItem) GetOwnerFieldName() string { func (self *DataItem) GetOwnerFieldName() string {
return "player_id" return "player_id"
} }
func (self *DataItem) GetIdFieldName() string { func (self *DataItem) GetIdFieldName() string {
return "id" return "id"
} }
func (self *DataItem) GetIdValue() uint64 { func (self *DataItem) GetIdValue() uint64 {
return uint64(self.Id) return uint64(self.Id)
} }
func (self *DataItem) Import(data interface{}) { func (self *DataItem) Import(data interface{}) {
switch data.(type) { switch data.(type) {
case DataItem: case DataItem:
{ {
row := data.(DataItem) row := data.(DataItem)
self.Id = row.Id self.Id = row.Id
self.Player_id = row.Player_id self.Player_id = row.Player_id
self.Proto_id = row.Proto_id self.Proto_id = row.Proto_id
self.Amount = row.Amount self.Amount = row.Amount
break break
} }
default: default:
break break
} }
} }
func (self *DataItem) Export(data []interface{}) { func (self *DataItem) Export(data []interface{}) {
data[0] = self.Id
data[1] = self.Player_id
data[2] = self.Proto_id
data[3] = self.Amount
}
data[0] = self.Id
data[1] = self.Player_id
data[2] = self.Proto_id
data[3] = self.Amount
}