604 lines
14 KiB
Go
604 lines
14 KiB
Go
package dbmeta_test
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
"os"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"git.bit5.ru/backend/db"
|
|
"git.bit5.ru/backend/dbmeta"
|
|
"git.bit5.ru/backend/meta"
|
|
|
|
"github.com/go-logr/stdr"
|
|
)
|
|
|
|
var logger = stdr.New(log.New(os.Stdout, "", log.Lshortfile))
|
|
|
|
func getDBC() *db.DBC {
|
|
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)
|
|
return dbc
|
|
}
|
|
|
|
func setupStorage(db *db.DBC) {
|
|
|
|
var sqls []string
|
|
sqls = append(sqls, "DROP TABLE IF EXISTS player")
|
|
sqls = append(sqls, `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
|
|
`)
|
|
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) {
|
|
ctx := context.TODO()
|
|
|
|
conn := getDBC()
|
|
setupStorage(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()
|
|
setupStorage(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()
|
|
setupStorage(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
|
|
}
|