Create & Init Project...

This commit is contained in:
2019-04-22 18:49:16 +08:00
commit fc4fa37393
25440 changed files with 4054998 additions and 0 deletions

View File

@@ -0,0 +1,69 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"cond_test.go",
"dao_test.go",
"keyword_test.go",
"mysql_test.go",
"redis_test.go",
"regexp_test.go",
"rule_test.go",
"transaction_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/antispam/conf:go_default_library",
"//app/service/main/antispam/model:go_default_library",
"//app/service/main/antispam/util:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"cond.go",
"dao.go",
"keyword.go",
"mysql.go",
"redis.go",
"regexp.go",
"rule.go",
"transaction.go",
],
importpath = "go-common/app/service/main/antispam/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/antispam/conf:go_default_library",
"//app/service/main/antispam/model:go_default_library",
"//app/service/main/antispam/util:go_default_library",
"//library/cache/redis:go_default_library",
"//library/database/sql:go_default_library",
"//library/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,24 @@
package dao
import "go-common/app/service/main/antispam/util"
// Condition .
type Condition struct {
*util.Pagination
Offset string
Limit string
Tags []string
Contents []string
Area string
Search string
State string
HitCounts string
Order, OrderBy string
LimitType, LimitScope string
StartTime, EndTime string
LastModifiedTime string
}

View File

@@ -0,0 +1 @@
package dao

View File

@@ -0,0 +1,128 @@
package dao
import (
"context"
"database/sql"
"time"
"go-common/app/service/main/antispam/conf"
"go-common/library/cache/redis"
xsql "go-common/library/database/sql"
)
// Executer .
type Executer interface {
Exec(ctx context.Context, SQL string, args ...interface{}) (sql.Result, error)
}
// Querier .
type Querier interface {
QueryRow(ctx context.Context, SQL string, args ...interface{}) *xsql.Row
Query(ctx context.Context, SQL string, args ...interface{}) (*xsql.Rows, error)
}
// KeywordDao .
type KeywordDao interface {
GetByID(context.Context, int64) (*Keyword, error)
GetByIDs(context.Context, []int64) ([]*Keyword, error)
GetByCond(context.Context, *Condition) ([]*Keyword, int64, error)
GetByOffsetLimit(context.Context, *Condition) ([]*Keyword, error)
GetByAreaAndContents(context.Context, *Condition) ([]*Keyword, error)
GetByAreaAndContent(context.Context, *Condition) (*Keyword, error)
GetRubbish(context.Context, *Condition) ([]*Keyword, error)
Insert(context.Context, *Keyword) (*Keyword, error)
Update(context.Context, *Keyword) (*Keyword, error)
DeleteByIDs(context.Context, []int64) ([]*Keyword, error)
}
// RuleDao .
type RuleDao interface {
GetByID(context.Context, int64) (*Rule, error)
GetByIDs(context.Context, []int64) ([]*Rule, error)
GetByCond(context.Context, *Condition) ([]*Rule, int64, error)
GetByArea(context.Context, *Condition) ([]*Rule, error)
GetByAreaAndTypeAndScope(context.Context, *Condition) (*Rule, error)
GetByAreaAndLimitType(context.Context, *Condition) ([]*Rule, error)
Insert(context.Context, *Rule) (*Rule, error)
Update(context.Context, *Rule) (*Rule, error)
}
// RegexpDao .
type RegexpDao interface {
GetByID(context.Context, int64) (*Regexp, error)
GetByIDs(context.Context, []int64) ([]*Regexp, error)
GetByCond(context.Context, *Condition) ([]*Regexp, int64, error)
GetByAreaAndContent(context.Context, *Condition) (*Regexp, error)
GetByContents(context.Context, []string) ([]*Regexp, error)
Insert(context.Context, *Regexp) (*Regexp, error)
Update(context.Context, *Regexp) (*Regexp, error)
}
// Tx .
type Tx interface {
Executer
RegexpTx
KeywordTx
RuleTx
Commit() error
Rollback() error
}
// KeywordTx .
type KeywordTx interface {
InsertKeyword(*Keyword) error
UpdateKeyword(*Keyword) error
}
// RegexpTx .
type RegexpTx interface {
InsertRegexp(*Regexp) error
UpdateRegexp(*Regexp) error
}
// RuleTx .
type RuleTx interface {
InsertRule(*Rule) error
UpdateRule(*Rule) error
}
// Dao .
type Dao struct {
// db *xsql.DB
redis *redis.Pool
redisExpire int
}
// New a dao and return.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
// db
// db: xsql.NewMySQL(c.MySQL.AntiSpam),
// redis
redis: redis.NewPool(c.Redis.Config),
redisExpire: int(time.Duration(c.Redis.IndexExpire) / time.Second),
}
return
}
// Ping check connection used in dao
func (d *Dao) Ping(c context.Context) (err error) {
if err = d.pingRedis(c); err != nil {
return
}
err = PingMySQL(c)
return
}
// Close close all connection.
func (d *Dao) Close() {
if d.redis != nil {
d.redis.Close()
}
Close()
}

View File

@@ -0,0 +1,40 @@
package dao
import (
"flag"
"go-common/app/service/main/antispam/conf"
"os"
"testing"
)
var (
d *Dao
kwi *KeywordDaoImpl
regdi *RegexpDaoImpl
rdi *RuleDaoImpl
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.community.antispam-service")
flag.Set("conf_token", "e0de72afaf4946ca836e9b7b459b833b")
flag.Set("tree_id", "11041")
flag.Set("conf_version", "docker-1")
flag.Set("deploy_env", "uat")
flag.Set("conf_host", "config.bilibili.co")
flag.Set("conf_path", "/tmp")
flag.Set("region", "sh")
flag.Set("zone", "sh001")
}
flag.Parse()
if err := conf.Init(""); err != nil {
panic(err)
}
Init(conf.Conf)
d = New(conf.Conf)
kwi = NewKeywordDao()
regdi = NewRegexpDao()
rdi = NewRuleDao()
m.Run()
os.Exit(0)
}

View File

@@ -0,0 +1,46 @@
CREATE TABLE keywords(
id INT(11) UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT '主键id',
area INT(11) NOT NULL DEFAULT 0 COMMENT '业务类型',
sender_id INT(11) NOT NULL DEFAULT 0 COMMENT '发送者的id',
content VARCHAR(40) NOT NULL COMMENT '关键字内容',
regexp_name VARCHAR(40) NOT NULL COMMENT '该关键字命中正则名称',
regexp_content VARCHAR(500) NOT NULL COMMENT '正则内容',
tag tinyint(4) NOT NULL DEFAULT 0 COMMENT '0:limit, 1:restrict, 2: whitelist, 3: blacklist',
hit_counts INT(11) NOT NULL DEFAULT 0 COMMENT '命中关键字次数',
state tinyint(4) NOT NULL DEFAULT 0 COMMENT '0:default, 1:deleted',
origin_content VARCHAR(1500) NOT NULL COMMENT '过滤前的内容',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
UNIQUE KEY `uk_area_content` (`area`, `content`),
KEY `ix_mtime` (`mtime`),
KEY `ix_area_state_ctime` (`area`,`state`, `ctime`)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='过滤限制关键字表';
CREATE TABLE regexps(
id INT(11) UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT '主键id',
name VARCHAR(20) NOT NULL COMMENT 'name',
area INT(11) NOT NULL DEFAULT 0 COMMENT '业务类型 1: reply, 2: imessage',
operation tinyint(4) NOT NULL DEFAULT 0 COMMENT '0: limit, 1: put into whitelist, 2: restrict limit, 3: ignore',
content VARCHAR(200) NOT NULL comment '正则内容',
state tinyint(4) NOT NULL DEFAULT 0 COMMENT '0:default, 1:deleted',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
KEY `ix_mtime` (`mtime`),
UNIQUE KEY `uk_area_content` (`area`, `content`)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='过滤限制正则表';
CREATE TABLE rate_limit_rules(
id INT(11) UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT '主键id',
area INT(11) NOT NULL DEFAULT 0 COMMENT '业务类型',
limit_type tinyint(4) NOT NULL DEFAULT 0 COMMENT '0: default, 1: strict',
limit_scope tinyint(4) NOT NULL DEFAULT 0 COMMENT '0: local, 1: global',
dur_sec int(11) NOT NULL DEFAULT 0 COMMENT '持续时间',
allowed_counts int(11) NOT NULL DEFAULT 0 COMMENT '允许发送次数',
state tinyint(4) NOT NULL DEFAULT 0 COMMENT '0:default, 1:deleted',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
KEY `ix_mtime` (`mtime`)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='频率规则表';
CREATE UNIQUE INDEX uk_area_limit_type_limit_scope ON rate_limit_rules (area, limit_type, limit_scope);

View File

@@ -0,0 +1,349 @@
package dao
import (
"context"
"fmt"
"strings"
"time"
"go-common/app/service/main/antispam/util"
"go-common/library/database/sql"
"go-common/library/log"
)
const (
columnKeywords = "id, area, content, regexp_name, tag, hit_counts, state, origin_content, ctime, mtime"
selectKeywordCountsSQL = `SELECT COUNT(1) FROM keywords %s`
selectKeywordsByCondSQL = `SELECT ` + columnKeywords + ` FROM keywords %s`
selectKeywordByIDsSQL = `SELECT ` + columnKeywords + ` FROM keywords WHERE id IN (%s)`
selectKeywordNeedRecycledSQL = `SELECT ` + columnKeywords + ` FROM keywords FORCE INDEX(ix_ctime) WHERE state = %s AND hit_counts < %s AND tag IN(%s) AND ctime BETWEEN '%s' AND '%s' LIMIT %d`
selectKeywordByOffsetLimitSQL = `SELECT ` + columnKeywords + ` FROM keywords WHERE area = %s AND id > %s AND tag IN(%s) AND state = 0 LIMIT %s`
selectKeywordByAreaAndContentsSQL = `SELECT ` + columnKeywords + ` FROM keywords WHERE area = %s AND content IN(%s)`
insertKeywordSQL = `INSERT INTO keywords(area, content, regexp_name, tag, hit_counts, origin_content) VALUES(?, ?, ?, ?, ?, ?)`
updateKeywordSQL = `UPDATE keywords SET content = ?, regexp_name = ?, tag = ?, hit_counts = ?, state = ?, origin_content = ?, ctime = ?, mtime = ? WHERE id = ?`
deleteKeywordByIDsSQL = `UPDATE keywords SET state = 1, hit_counts = 0, mtime = ? WHERE id IN (%s)`
)
const (
// KeywordTagDefaultLimit .
KeywordTagDefaultLimit int = iota
// KeywordTagRestrictLimit .
KeywordTagRestrictLimit
// KeywordTagWhite .
KeywordTagWhite
// KeywordTagBlack .
KeywordTagBlack
)
// KeywordDaoImpl .
type KeywordDaoImpl struct{}
// Keyword .
type Keyword struct {
ID int64 `db:"id"`
Area int `db:"area"`
Tag int `db:"tag"`
State int `db:"state"`
HitCounts int64 `db:"hit_counts"`
RegexpName string `db:"regexp_name"`
Content string `db:"content"`
OriginContent string `db:"origin_content"`
CTime time.Time `db:"ctime"`
MTime time.Time `db:"mtime"`
}
// NewKeywordDao .
func NewKeywordDao() *KeywordDaoImpl {
return &KeywordDaoImpl{}
}
// GetRubbish .
func (*KeywordDaoImpl) GetRubbish(ctx context.Context, cond *Condition) (keywords []*Keyword, err error) {
querySQL := fmt.Sprintf(selectKeywordNeedRecycledSQL,
cond.State,
cond.HitCounts,
util.StrSliToSQLVarchars(cond.Tags),
cond.StartTime,
cond.EndTime,
cond.PerPage,
)
log.Info("get rubbish keywords rawSQL: %s", querySQL)
ks, err := queryKeywords(ctx, db, querySQL)
if err != nil {
return nil, err
}
return ks, nil
}
// GetByOffsetLimit .
func (*KeywordDaoImpl) GetByOffsetLimit(ctx context.Context, cond *Condition) (keywords []*Keyword, err error) {
return queryKeywords(ctx, db, fmt.Sprintf(selectKeywordByOffsetLimitSQL, cond.Area,
cond.Offset, util.StrSliToSQLVarchars(cond.Tags), cond.Limit))
}
// GetByCond .
func (*KeywordDaoImpl) GetByCond(ctx context.Context, cond *Condition) (keywords []*Keyword, totalCounts int64, err error) {
sqlConds := make([]string, 0)
if cond.Search != "" {
sqlConds = append(sqlConds, fmt.Sprintf("content LIKE '%%%s%%'", cond.Search))
}
if len(cond.Contents) > 0 {
sqlConds = append(sqlConds, fmt.Sprintf("content IN (%s)", util.StrSliToSQLVarchars(cond.Tags)))
}
if cond.LastModifiedTime != "" {
sqlConds = append(sqlConds, fmt.Sprintf("mtime >= '%s'", cond.LastModifiedTime))
cond.OrderBy = ""
}
if cond.StartTime != "" || cond.EndTime != "" {
if cond.StartTime != "" && cond.EndTime != "" {
sqlConds = append(sqlConds, fmt.Sprintf("ctime BETWEEN '%s' AND '%s'", cond.StartTime, cond.EndTime))
} else if cond.StartTime != "" {
sqlConds = append(sqlConds, fmt.Sprintf("ctime >= '%s'", cond.StartTime))
} else {
sqlConds = append(sqlConds, fmt.Sprintf("ctime <= '%s'", cond.EndTime))
}
}
if cond.State != "" {
sqlConds = append(sqlConds, fmt.Sprintf("state = %s", cond.State))
}
if cond.Area != "" {
sqlConds = append(sqlConds, fmt.Sprintf("area = %s", cond.Area))
}
if len(cond.Tags) > 0 {
sqlConds = append(sqlConds, fmt.Sprintf("tag IN(%s)", util.StrSliToSQLVarchars(cond.Tags)))
}
var optionSQL string
if len(sqlConds) > 0 {
optionSQL = fmt.Sprintf("WHERE %s", strings.Join(sqlConds, " AND "))
}
var limitSQL string
if cond.Pagination != nil {
queryCountsSQL := fmt.Sprintf(selectKeywordCountsSQL, optionSQL)
log.Info("queryCounts sql: %s", queryCountsSQL)
totalCounts, err = GetTotalCounts(ctx, db, queryCountsSQL)
if err != nil {
return nil, 0, err
}
offset, limit := cond.OffsetLimit(totalCounts)
if limit == 0 {
return nil, 0, ErrResourceNotExist
}
limitSQL = fmt.Sprintf("LIMIT %d, %d", offset, limit)
}
if cond.OrderBy != "" {
optionSQL = fmt.Sprintf("%s ORDER BY %s %s", optionSQL, cond.OrderBy, cond.Order)
}
if limitSQL != "" {
optionSQL = fmt.Sprintf("%s %s", optionSQL, limitSQL)
}
querySQL := fmt.Sprintf(selectKeywordsByCondSQL, optionSQL)
log.Info("OptionSQL(%s), GetByCondSQL(%s)", optionSQL, querySQL)
keywords, err = queryKeywords(ctx, db, querySQL)
if err != nil {
return nil, 0, err
}
if totalCounts == 0 {
totalCounts = int64(len(keywords))
}
return keywords, totalCounts, nil
}
// GetByAreaAndContents .
func (*KeywordDaoImpl) GetByAreaAndContents(ctx context.Context,
cond *Condition) ([]*Keyword, error) {
querySQL := fmt.Sprintf(selectKeywordByAreaAndContentsSQL,
cond.Area, util.StrSliToSQLVarchars(cond.Contents))
ks, err := queryKeywords(ctx, db, querySQL)
if err != nil {
return nil, err
}
res := make([]*Keyword, len(cond.Contents))
for i, c := range cond.Contents {
for _, k := range ks {
if strings.EqualFold(k.Content, c) {
res[i] = k
}
}
}
return res, nil
}
// GetByAreaAndContent .
func (kdi *KeywordDaoImpl) GetByAreaAndContent(ctx context.Context,
cond *Condition) (*Keyword, error) {
ks, err := kdi.GetByAreaAndContents(ctx, cond)
if err != nil {
return nil, err
}
if ks[0] == nil {
return nil, ErrResourceNotExist
}
return ks[0], nil
}
// Update .
func (kdi *KeywordDaoImpl) Update(ctx context.Context,
k *Keyword) (*Keyword, error) {
if err := updateKeyword(ctx, db, k); err != nil {
return nil, err
}
return kdi.GetByID(ctx, k.ID)
}
// Insert .
func (kdi *KeywordDaoImpl) Insert(ctx context.Context, k *Keyword) (*Keyword, error) {
if err := insertKeyword(ctx, db, k); err != nil {
return nil, err
}
return kdi.GetByID(ctx, k.ID)
}
// DeleteByIDs .
func (kdi *KeywordDaoImpl) DeleteByIDs(ctx context.Context, ids []int64) ([]*Keyword, error) {
if err := deleteKeywordByIDs(ctx, db, ids); err != nil {
return nil, err
}
return kdi.GetByIDs(ctx, ids)
}
// GetByID .
func (kdi *KeywordDaoImpl) GetByID(ctx context.Context, id int64) (*Keyword, error) {
ks, err := kdi.GetByIDs(ctx, []int64{id})
if err != nil {
return nil, err
}
if ks[0] == nil {
return nil, ErrResourceNotExist
}
return ks[0], nil
}
// GetByIDs .
func (*KeywordDaoImpl) GetByIDs(ctx context.Context, ids []int64) ([]*Keyword, error) {
ks, err := queryKeywords(ctx, db,
fmt.Sprintf(selectKeywordByIDsSQL, util.IntSliToSQLVarchars(ids)))
if err != nil {
return nil, err
}
res := make([]*Keyword, len(ids))
for i, id := range ids {
for _, k := range ks {
if k.ID == id {
res[i] = k
}
}
}
return res, nil
}
func insertKeyword(ctx context.Context, executer Executer, k *Keyword) error {
defaultHitCount := 1
res, err := executer.Exec(ctx,
insertKeywordSQL,
k.Area,
k.Content,
k.RegexpName,
k.Tag,
defaultHitCount,
k.OriginContent,
)
if err != nil {
log.Error("%v", err)
return err
}
lastID, err := res.LastInsertId()
if err != nil {
log.Error("%v", err)
return err
}
k.ID = lastID
return nil
}
func updateKeyword(ctx context.Context, executer Executer, k *Keyword) error {
_, err := executer.Exec(ctx,
updateKeywordSQL,
k.Content,
k.RegexpName,
k.Tag,
k.HitCounts,
k.State,
k.OriginContent,
k.CTime,
time.Now(),
k.ID,
)
if err != nil {
log.Error("%v", err)
return err
}
return nil
}
func deleteKeywordByIDs(ctx context.Context, executer Executer, ids []int64) error {
rawSQL := fmt.Sprintf(deleteKeywordByIDsSQL, util.IntSliToSQLVarchars(ids))
if _, err := executer.Exec(ctx, rawSQL, time.Now()); err != nil {
log.Error("Error: %v, RawSQL: %s", err, rawSQL)
return err
}
return nil
}
func queryKeywords(ctx context.Context, q Querier, rawSQL string) ([]*Keyword, error) {
// NOTICE: this MotherFucker Query() will never return `ErrNoRows` when there is no rows found !
rows, err := q.Query(ctx, rawSQL)
if err == sql.ErrNoRows {
return nil, ErrResourceNotExist
} else if err != nil {
log.Error("ctx: %+v, Error: %v, RawSQL: %s", ctx, err, rawSQL)
return nil, err
}
defer rows.Close()
log.Info("Query sql: %q", rawSQL)
ks, err := mapRowToKeywords(rows)
if err != nil {
return nil, err
}
if len(ks) == 0 {
return nil, ErrResourceNotExist
}
return ks, nil
}
func mapRowToKeywords(rows *sql.Rows) (ks []*Keyword, err error) {
for rows.Next() {
k := Keyword{}
err = rows.Scan(
&k.ID,
&k.Area,
&k.Content,
&k.RegexpName,
&k.Tag,
&k.HitCounts,
&k.State,
&k.OriginContent,
&k.CTime,
&k.MTime,
)
if err != nil {
log.Error("%v", err)
return nil, err
}
ks = append(ks, &k)
}
if err = rows.Err(); err != nil {
log.Error("%v", err)
return nil, err
}
return ks, nil
}

View File

@@ -0,0 +1,151 @@
package dao
import (
"context"
"fmt"
"go-common/app/service/main/antispam/util"
"math/rand"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func testKeywordDaoImplGetRubbish(t *testing.T) {
var (
c = context.TODO()
cond = &Condition{Pagination: &util.Pagination{CurPage: 1, PerPage: 10}, Tags: []string{"reply"}, Area: "reply", Offset: "1", State: "0", HitCounts: "0", StartTime: "2018-8-1 16:36:48", EndTime: "2018-8-21 16:36:48"}
)
convey.Convey("GetRubbish", t, func(ctx convey.C) {
_, err := kwi.GetRubbish(c, cond)
ctx.Convey("Then err should be nil.keywords should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func testKeywordDaoImplGetByOffsetLimit(t *testing.T) {
var (
c = context.TODO()
cond = &Condition{Pagination: &util.Pagination{CurPage: 1, PerPage: 10}, Tags: []string{"reply"}, Area: "reply", Offset: "1", State: "0", HitCounts: "0", StartTime: "2018-8-1 16:36:48", EndTime: "2018-8-21 16:36:48"}
)
convey.Convey("GetByOffsetLimit", t, func(ctx convey.C) {
keywords, err := kwi.GetByOffsetLimit(c, cond)
ctx.Convey("Then err should be nil.keywords should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(keywords, convey.ShouldNotBeNil)
})
})
}
func testKeywordDaoImplGetByCond(t *testing.T) {
var (
c = context.TODO()
cond = &Condition{Pagination: &util.Pagination{CurPage: 1, PerPage: 10}, Tags: []string{"reply"}, Area: "reply", Offset: "1", State: "0", HitCounts: "0", StartTime: "2018-8-1 16:36:48", EndTime: "2018-8-21 16:36:48"}
)
convey.Convey("GetByCond", t, func(ctx convey.C) {
keywords, totalCounts, err := kwi.GetByCond(c, cond)
ctx.Convey("Then err should be nil.keywords,totalCounts should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(totalCounts, convey.ShouldNotBeNil)
ctx.So(keywords, convey.ShouldNotBeNil)
})
})
}
func testKeywordDaoImplGetByAreaAndContents(t *testing.T) {
var (
c = context.TODO()
cond = &Condition{Pagination: &util.Pagination{CurPage: 1, PerPage: 10}, Tags: []string{"reply"}, Area: "reply", Offset: "1", State: "0", HitCounts: "0", StartTime: "2018-8-1 16:36:48", EndTime: "2018-8-21 16:36:48"}
)
convey.Convey("GetByAreaAndContents", t, func(ctx convey.C) {
p1, err := kwi.GetByAreaAndContents(c, cond)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func testKeywordDaoImplGetByAreaAndContent(t *testing.T) {
var (
c = context.TODO()
cond = &Condition{Pagination: &util.Pagination{CurPage: 1, PerPage: 10}, Tags: []string{"reply"}, Area: "reply", Offset: "1", State: "0", HitCounts: "0", StartTime: "2018-8-1 16:36:48", EndTime: "2018-8-21 16:36:48"}
)
convey.Convey("GetByAreaAndContent", t, func(ctx convey.C) {
p1, err := kwi.GetByAreaAndContent(c, cond)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestKeywordDaoImplUpdate(t *testing.T) {
var (
c = context.TODO()
k = &Keyword{ID: 1, Content: fmt.Sprint(rand.Int63())}
)
convey.Convey("Update", t, func(ctx convey.C) {
p1, err := kwi.Update(c, k)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestKeywordDaoImplInsert(t *testing.T) {
var (
c = context.TODO()
k = &Keyword{Content: fmt.Sprint(rand.Int63())}
)
convey.Convey("Insert", t, func(ctx convey.C) {
p1, err := kwi.Insert(c, k)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestKeywordDaoImplDeleteByIDs(t *testing.T) {
var (
c = context.TODO()
ids = []int64{1}
)
convey.Convey("DeleteByIDs", t, func(ctx convey.C) {
p1, err := kwi.DeleteByIDs(c, ids)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestKeywordDaoImplGetByID(t *testing.T) {
var (
c = context.TODO()
id = int64(1)
)
convey.Convey("GetByID", t, func(ctx convey.C) {
p1, err := kwi.GetByID(c, id)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestKeywordDaoImplGetByIDs(t *testing.T) {
var (
c = context.TODO()
ids = []int64{1, 2, 3}
)
convey.Convey("GetByIDs", t, func(ctx convey.C) {
p1, err := kwi.GetByIDs(c, ids)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,77 @@
package dao
import (
"context"
"errors"
"go-common/app/service/main/antispam/conf"
"go-common/library/database/sql"
"go-common/library/log"
)
const (
// AreaReply .
AreaReply int = iota + 1
// AreaIMessage .
AreaIMessage
// AreaLiveDM .
AreaLiveDM
// AreaMainSiteDM .
AreaMainSiteDM
)
const (
// StateDefault .
StateDefault int = iota
// StateDeleted .
StateDeleted
)
var (
// ErrPingDao .
ErrPingDao = errors.New("Ping dao error")
// ErrResourceNotExist .
ErrResourceNotExist = errors.New("Resource Not Exist")
// ErrParams .
ErrParams = errors.New("wrong params")
)
// GetTotalCounts .
func GetTotalCounts(ctx context.Context, q Querier, selectCountsSQL string) (int64, error) {
var totalCounts int64
if err := q.QueryRow(ctx, selectCountsSQL).Scan(&totalCounts); err != nil {
log.Error("Error: %v, sql: %s", err, selectCountsSQL)
return 0, err
}
log.Info("GetTotalCounts query sql: %s", selectCountsSQL)
return totalCounts, nil
}
// PingMySQL .
func PingMySQL(ctx context.Context) error {
if db != nil {
if err := db.Ping(ctx); err != nil {
log.Error("%v", err)
return err
}
}
return nil
}
// Close .
func Close() {
if db != nil {
db.Close()
}
}
// Init .
func Init(conf *conf.Config) (ok bool) {
if db == nil {
db = sql.NewMySQL(conf.MySQL.AntiSpam)
}
return db != nil
}
var db *sql.DB

View File

@@ -0,0 +1,28 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoPingMySQL(t *testing.T) {
var (
c = context.TODO()
)
convey.Convey("PingMySQL", t, func(ctx convey.C) {
err := PingMySQL(c)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoClose(t *testing.T) {
convey.Convey("Close", t, func(ctx convey.C) {
Close()
ctx.Convey("No return values", func(ctx convey.C) {
})
})
}

View File

@@ -0,0 +1,361 @@
package dao
import (
"context"
"fmt"
"go-common/app/service/main/antispam/model"
"go-common/library/cache/redis"
"go-common/library/log"
)
const (
_regexpsKey = "regexps"
_localCountsKey = "resource_id:%d:keyword_id:%d:local_limit_counts"
_totalCountsKey = "keyword_id:%d:total_counts"
_globalCountsKey = "keyword_id:%d:global_limit_counts"
_keywordsSenderIDsKey = "keyword_id:%d:sender_ids"
_rulesKey = "rule:area:%s:limit_type:%s"
_areaSendersKey = "area:%s:sender_id:%d"
)
func sendersKey(keywordID int64) string {
return fmt.Sprintf(_keywordsSenderIDsKey, keywordID)
}
func areaSendersKey(area string, senderID int64) string {
return fmt.Sprintf(_areaSendersKey, area, senderID)
}
func totalCountsKey(keywordID int64) string {
return fmt.Sprintf(_totalCountsKey, keywordID)
}
func localCountsKey(keywordID, oid int64) string {
return fmt.Sprintf(_localCountsKey, oid, keywordID)
}
func globalCountsKey(keywordID int64) string {
return fmt.Sprintf(_globalCountsKey, keywordID)
}
func rulesKey(area, limitType string) string {
return fmt.Sprintf(_rulesKey, area, limitType)
}
// pingRedis check redis connection
func (d *Dao) pingRedis(c context.Context) (err error) {
conn := d.redis.Get(c)
_, err = conn.Do("SET", "PING", "PONG")
conn.Close()
return
}
// CntSendersCache .
func (d *Dao) CntSendersCache(c context.Context, keywordID int64) (cnt int64, err error) {
var (
key = sendersKey(keywordID)
conn = d.redis.Get(c)
)
defer conn.Close()
if cnt, err = redis.Int64(conn.Do("ZCARD", key)); err != nil {
log.Error("redis.Int64(conn.Do(ZCARD, %s)) error(%v)", key, err)
}
return
}
// GlobalLocalLimitCache .
func (d *Dao) GlobalLocalLimitCache(c context.Context, keywordID, oid int64) ([]int64, error) {
var (
globalKey = globalCountsKey(keywordID)
localKey = localCountsKey(keywordID, oid)
conn = d.redis.Get(c)
)
defer conn.Close()
if err := conn.Send("GET", globalKey); err != nil {
log.Error("%v", err)
return nil, err
}
if err := conn.Send("GET", localKey); err != nil {
log.Error("%v", err)
return nil, err
}
if err := conn.Flush(); err != nil {
log.Error("%v", err)
return nil, err
}
counts := make([]int64, 0)
for i := 0; i < 2; i++ {
count, err := redis.Int64(conn.Receive())
if err == nil || err == redis.ErrNil {
counts = append(counts, count)
continue
}
log.Error("%v", err)
return nil, err
}
return counts, nil
}
// IncrGlobalLimitCache .
func (d *Dao) IncrGlobalLimitCache(c context.Context, keywordID int64) (int64, error) {
var (
key = globalCountsKey(keywordID)
conn = d.redis.Get(c)
)
defer conn.Close()
count, err := redis.Int64(conn.Do("INCR", key))
if err != nil {
log.Error("%v", err)
return 0, err
}
return count, nil
}
// IncrLocalLimitCache .
func (d *Dao) IncrLocalLimitCache(c context.Context, keywordID, oid int64) (int64, error) {
var (
key = localCountsKey(keywordID, oid)
conn = d.redis.Get(c)
)
defer conn.Close()
count, err := redis.Int64(conn.Do("INCR", key))
if err != nil {
log.Error("%v", err)
return 0, err
}
return count, nil
}
// LocalLimitExpire .
func (d *Dao) LocalLimitExpire(c context.Context, keywordID, oid, dur int64) error {
var (
key = localCountsKey(keywordID, oid)
conn = d.redis.Get(c)
)
defer conn.Close()
if _, err := conn.Do("EXPIRE", key, dur); err != nil {
log.Error("%v", err)
return err
}
return nil
}
// GlobalLimitExpire .
func (d *Dao) GlobalLimitExpire(c context.Context, keywordID, dur int64) error {
var (
key = globalCountsKey(keywordID)
conn = d.redis.Get(c)
)
defer conn.Close()
if _, err := conn.Do("EXPIRE", key, dur); err != nil {
log.Error("%v", err)
return err
}
return nil
}
// DelRegexpCache .
func (d *Dao) DelRegexpCache(c context.Context) error {
conn := d.redis.Get(c)
defer conn.Close()
if _, err := conn.Do("DEL", _regexpsKey); err != nil {
log.Error("%v", err)
return err
}
return nil
}
// DelRulesCache .
func (d *Dao) DelRulesCache(c context.Context, area, limitType string) error {
var (
key = rulesKey(area, limitType)
conn = d.redis.Get(c)
)
defer conn.Close()
if _, err := conn.Do("DEL", key); err != nil {
log.Error("%v", err)
return err
}
return nil
}
// AreaSendersExpire .
func (d *Dao) AreaSendersExpire(c context.Context, area string, senderID, dur int64) error {
var (
key = areaSendersKey(area, senderID)
conn = d.redis.Get(c)
)
defer conn.Close()
if _, err := conn.Do("EXPIRE", key, dur); err != nil {
log.Error("%v", err)
return err
}
return nil
}
// IncrAreaSendersCache .
func (d *Dao) IncrAreaSendersCache(c context.Context, area string, senderID int64) (int64, error) {
var (
key = areaSendersKey(area, senderID)
conn = d.redis.Get(c)
)
defer conn.Close()
count, err := redis.Int64(conn.Do("INCR", key))
if err != nil {
log.Error("%v", err)
return 0, err
}
return count, nil
}
// AllSendersCache .
func (d *Dao) AllSendersCache(c context.Context, keywordID int64) ([]string, error) {
var (
key = sendersKey(keywordID)
conn = d.redis.Get(c)
)
defer conn.Close()
r, err := redis.Strings(conn.Do("ZRANGEBYSCORE", key, "-inf", "+inf"))
if err != nil {
log.Error("%v", err)
return nil, err
}
return r, nil
}
// SendersCache .
func (d *Dao) SendersCache(c context.Context, keywordID, limit, offset int64) ([]string, error) {
var (
key = sendersKey(keywordID)
conn = d.redis.Get(c)
)
defer conn.Close()
r, err := redis.Strings(conn.Do("ZRANGEBYSCORE", key, "-inf", "+inf", "LIMIT", limit, offset))
if err != nil {
log.Error("%v", err)
return nil, err
}
return r, nil
}
// TotalLimitExpire .
func (d *Dao) TotalLimitExpire(c context.Context, keywordID, dur int64) error {
var (
key = totalCountsKey(keywordID)
conn = d.redis.Get(c)
)
defer conn.Close()
if _, err := conn.Do("EXPIRE", key, dur); err != nil {
log.Error("%v", err)
return err
}
return nil
}
// IncrTotalLimitCache .
func (d *Dao) IncrTotalLimitCache(c context.Context, keywordID int64) (int64, error) {
var (
key = totalCountsKey(keywordID)
conn = d.redis.Get(c)
)
defer conn.Close()
count, err := redis.Int64(conn.Do("INCR", key))
if err != nil {
log.Error("%v", err)
return 0, err
}
return count, nil
}
// ZaddSendersCache insert into sortedset and return total counts of sorted set
func (d *Dao) ZaddSendersCache(c context.Context, keywordID, score, senderID int64) (int64, error) {
var (
key = sendersKey(keywordID)
val = fmt.Sprintf("%d", senderID)
conn = d.redis.Get(c)
)
defer conn.Close()
_, err := redis.Int64(conn.Do("ZADD", key, score, val))
if err != nil {
log.Error("%v", err)
return 0, err
}
r, err := redis.Int64(conn.Do("ZCARD", key))
if err != nil {
log.Error("%v", err)
return 0, err
}
return r, nil
}
// ZremSendersCache return the number of memebers removed from the sorted set
func (d *Dao) ZremSendersCache(c context.Context, keywordID int64, senderIDStr string) (int64, error) {
var (
key = sendersKey(keywordID)
conn = d.redis.Get(c)
)
defer conn.Close()
r, err := redis.Int64(conn.Do("ZREM", key, senderIDStr))
if err != nil {
log.Error("%v", err)
return 0, err
}
return r, nil
}
// DelKeywordRelatedCache .
func (d *Dao) DelKeywordRelatedCache(c context.Context, ks []*model.Keyword) error {
var conn = d.redis.Get(c)
defer conn.Close()
for _, v := range ks {
if err := conn.Send("DEL", totalCountsKey(v.ID)); err != nil {
log.Error("%v", err)
return err
}
if err := conn.Send("DEL", sendersKey(v.ID)); err != nil {
log.Error("%v", err)
return err
}
}
if err := conn.Flush(); err != nil {
log.Error("%v", err)
return err
}
for i := 0; i < len(ks)*2; i++ {
if _, err := conn.Receive(); err != nil {
log.Error("conn.Receive() error(%v)", err)
return err
}
}
return nil
}
// DelCountRelatedCache .
func (d *Dao) DelCountRelatedCache(c context.Context, k *model.Keyword) error {
var conn = d.redis.Get(c)
defer conn.Close()
if err := conn.Send("DEL", globalCountsKey(k.ID)); err != nil {
log.Error("%v", err)
return err
}
if err := conn.Send("DEL", localCountsKey(k.ID, k.SenderID)); err != nil {
log.Error("%v", err)
return err
}
if err := conn.Send("DEL", sendersKey(k.ID)); err != nil {
log.Error("%v", err)
return err
}
if err := conn.Flush(); err != nil {
log.Error("%v", err)
return err
}
for i := 0; i < 3; i++ {
if _, err := conn.Receive(); err != nil {
log.Error("conn.Receive() error(%v)", err)
return err
}
}
return nil
}

View File

@@ -0,0 +1,354 @@
package dao
import (
"context"
"go-common/app/service/main/antispam/model"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaosendersKey(t *testing.T) {
var (
keywordID = int64(0)
)
convey.Convey("sendersKey", t, func(ctx convey.C) {
p1 := sendersKey(keywordID)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoareaSendersKey(t *testing.T) {
var (
area = ""
senderID = int64(0)
)
convey.Convey("areaSendersKey", t, func(ctx convey.C) {
p1 := areaSendersKey(area, senderID)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaototalCountsKey(t *testing.T) {
var (
keywordID = int64(0)
)
convey.Convey("totalCountsKey", t, func(ctx convey.C) {
p1 := totalCountsKey(keywordID)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaolocalCountsKey(t *testing.T) {
var (
keywordID = int64(0)
oid = int64(0)
)
convey.Convey("localCountsKey", t, func(ctx convey.C) {
p1 := localCountsKey(keywordID, oid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoglobalCountsKey(t *testing.T) {
var (
keywordID = int64(0)
)
convey.Convey("globalCountsKey", t, func(ctx convey.C) {
p1 := globalCountsKey(keywordID)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaorulesKey(t *testing.T) {
var (
area = ""
limitType = ""
)
convey.Convey("rulesKey", t, func(ctx convey.C) {
p1 := rulesKey(area, limitType)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaopingRedis(t *testing.T) {
var (
c = context.TODO()
)
convey.Convey("pingRedis", t, func(ctx convey.C) {
err := d.pingRedis(c)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoCntSendersCache(t *testing.T) {
var (
c = context.TODO()
keywordID = int64(0)
)
convey.Convey("CntSendersCache", t, func(ctx convey.C) {
cnt, err := d.CntSendersCache(c, keywordID)
ctx.Convey("Then err should be nil.cnt should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(cnt, convey.ShouldNotBeNil)
})
})
}
func TestDaoGlobalLocalLimitCache(t *testing.T) {
var (
c = context.TODO()
keywordID = int64(0)
oid = int64(0)
)
convey.Convey("GlobalLocalLimitCache", t, func(ctx convey.C) {
p1, err := d.GlobalLocalLimitCache(c, keywordID, oid)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoIncrGlobalLimitCache(t *testing.T) {
var (
c = context.TODO()
keywordID = int64(0)
)
convey.Convey("IncrGlobalLimitCache", t, func(ctx convey.C) {
p1, err := d.IncrGlobalLimitCache(c, keywordID)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoIncrLocalLimitCache(t *testing.T) {
var (
c = context.TODO()
keywordID = int64(0)
oid = int64(0)
)
convey.Convey("IncrLocalLimitCache", t, func(ctx convey.C) {
p1, err := d.IncrLocalLimitCache(c, keywordID, oid)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoLocalLimitExpire(t *testing.T) {
var (
c = context.TODO()
keywordID = int64(0)
oid = int64(0)
dur = int64(0)
)
convey.Convey("LocalLimitExpire", t, func(ctx convey.C) {
err := d.LocalLimitExpire(c, keywordID, oid, dur)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoGlobalLimitExpire(t *testing.T) {
var (
c = context.TODO()
keywordID = int64(0)
dur = int64(0)
)
convey.Convey("GlobalLimitExpire", t, func(ctx convey.C) {
err := d.GlobalLimitExpire(c, keywordID, dur)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoDelRegexpCache(t *testing.T) {
var (
c = context.TODO()
)
convey.Convey("DelRegexpCache", t, func(ctx convey.C) {
err := d.DelRegexpCache(c)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoDelRulesCache(t *testing.T) {
var (
c = context.TODO()
area = ""
limitType = ""
)
convey.Convey("DelRulesCache", t, func(ctx convey.C) {
err := d.DelRulesCache(c, area, limitType)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoAreaSendersExpire(t *testing.T) {
var (
c = context.TODO()
area = ""
senderID = int64(0)
dur = int64(0)
)
convey.Convey("AreaSendersExpire", t, func(ctx convey.C) {
err := d.AreaSendersExpire(c, area, senderID, dur)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoIncrAreaSendersCache(t *testing.T) {
var (
c = context.TODO()
area = ""
senderID = int64(0)
)
convey.Convey("IncrAreaSendersCache", t, func(ctx convey.C) {
p1, err := d.IncrAreaSendersCache(c, area, senderID)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoAllSendersCache(t *testing.T) {
var (
c = context.TODO()
keywordID = int64(0)
)
convey.Convey("AllSendersCache", t, func(ctx convey.C) {
p1, err := d.AllSendersCache(c, keywordID)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoSendersCache(t *testing.T) {
var (
c = context.TODO()
keywordID = int64(0)
limit = int64(0)
offset = int64(0)
)
convey.Convey("SendersCache", t, func(ctx convey.C) {
p1, err := d.SendersCache(c, keywordID, limit, offset)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoTotalLimitExpire(t *testing.T) {
var (
c = context.TODO()
keywordID = int64(0)
dur = int64(0)
)
convey.Convey("TotalLimitExpire", t, func(ctx convey.C) {
err := d.TotalLimitExpire(c, keywordID, dur)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoIncrTotalLimitCache(t *testing.T) {
var (
c = context.TODO()
keywordID = int64(0)
)
convey.Convey("IncrTotalLimitCache", t, func(ctx convey.C) {
p1, err := d.IncrTotalLimitCache(c, keywordID)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoZaddSendersCache(t *testing.T) {
var (
c = context.TODO()
keywordID = int64(0)
score = int64(0)
senderID = int64(0)
)
convey.Convey("ZaddSendersCache", t, func(ctx convey.C) {
p1, err := d.ZaddSendersCache(c, keywordID, score, senderID)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoZremSendersCache(t *testing.T) {
var (
c = context.TODO()
keywordID = int64(1)
senderIDStr = ""
)
convey.Convey("ZremSendersCache", t, func(ctx convey.C) {
p1, err := d.ZremSendersCache(c, keywordID, senderIDStr)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoDelKeywordRelatedCache(t *testing.T) {
var (
c = context.TODO()
ks = []*model.Keyword{}
)
convey.Convey("DelKeywordRelatedCache", t, func(ctx convey.C) {
err := d.DelKeywordRelatedCache(c, ks)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoDelCountRelatedCache(t *testing.T) {
var (
c = context.TODO()
k = &model.Keyword{}
)
convey.Convey("DelCountRelatedCache", t, func(ctx convey.C) {
err := d.DelCountRelatedCache(c, k)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,270 @@
package dao
import (
"context"
"fmt"
"strings"
"time"
"go-common/app/service/main/antispam/util"
"go-common/library/database/sql"
"go-common/library/log"
)
const (
columnsRegexp = `id, admin_id, area, name, operation, content, state, ctime, mtime`
selectRegexpCountsSQL = `SELECT COUNT(1) FROM regexps %s`
selectRegexpsByCondSQL = `SELECT ` + columnsRegexp + ` FROM regexps %s`
selectRegexpByIDsSQL = `SELECT ` + columnsRegexp + ` FROM regexps WHERE id IN(%s)`
selectRegexpByContentsSQL = `SELECT ` + columnsRegexp + ` FROM regexps WHERE content IN(%s)`
selectRegexpByAreaAndContentSQL = `SELECT ` + columnsRegexp + ` FROM regexps WHERE area = %s AND content IN(%s)`
insertRegexpSQL = `INSERT INTO regexps(id, admin_id, area, name, operation, content, state) VALUES(?, ?, ?, ?, ?, ?, ?)`
updateRegexpSQL = `UPDATE regexps SET admin_id = ?, name = ?, content = ?, operation = ?, state = ?, mtime = ? WHERE id = ?`
)
const (
// OperationLimit .
OperationLimit int = iota
// OperationPutToWhiteList .
OperationPutToWhiteList
// OperationRestrictLimit .
OperationRestrictLimit
// OperationIgnore .
OperationIgnore
)
// RegexpDaoImpl .
type RegexpDaoImpl struct{}
// Regexp .
type Regexp struct {
ID int64 `db:"id"`
Area int `db:"area"`
Name string `db:"name"`
AdminID int64 `db:"admin_id"`
Operation int `db:"operation"`
Content string `db:"content"`
State int `db:"state"`
CTime time.Time `db:"ctime"`
MTime time.Time `db:"mtime"`
}
// NewRegexpDao .
func NewRegexpDao() *RegexpDaoImpl {
return &RegexpDaoImpl{}
}
// GetByCond .
func (*RegexpDaoImpl) GetByCond(ctx context.Context,
cond *Condition) (regexps []*Regexp, totalCounts int64, err error) {
sqlConds := make([]string, 0)
if cond.Area != "" {
sqlConds = append(sqlConds, fmt.Sprintf("area = %s", cond.Area))
}
if cond.State != "" {
sqlConds = append(sqlConds, fmt.Sprintf("state = %s", cond.State))
}
var optionSQL string
if len(sqlConds) > 0 {
optionSQL = fmt.Sprintf("WHERE %s", strings.Join(sqlConds, " AND "))
}
var limitSQL string
if cond.Pagination != nil {
queryCountsSQL := fmt.Sprintf(selectRegexpCountsSQL, optionSQL)
totalCounts, err = GetTotalCounts(ctx, db, queryCountsSQL)
if err != nil {
return nil, 0, err
}
offset, limit := cond.OffsetLimit(totalCounts)
if limit == 0 {
return nil, 0, ErrResourceNotExist
}
limitSQL = fmt.Sprintf("LIMIT %d, %d", offset, limit)
}
if cond.OrderBy != "" {
optionSQL = fmt.Sprintf("%s ORDER BY %s %s", optionSQL, cond.OrderBy, cond.Order)
}
if limitSQL != "" {
optionSQL = fmt.Sprintf("%s %s", optionSQL, limitSQL)
}
querySQL := fmt.Sprintf(selectRegexpsByCondSQL, optionSQL)
log.Info("OptionSQL(%s), GetByCondSQL(%s)", optionSQL, querySQL)
regexps, err = queryRegexps(ctx, db, querySQL)
if err != nil {
return nil, totalCounts, err
}
return regexps, totalCounts, nil
}
// Update .
func (rdi *RegexpDaoImpl) Update(ctx context.Context, r *Regexp) (*Regexp, error) {
err := updateRegexp(ctx, db, r)
if err != nil {
return nil, err
}
return rdi.GetByID(ctx, r.ID)
}
// Insert .
func (rdi *RegexpDaoImpl) Insert(ctx context.Context, r *Regexp) (*Regexp, error) {
err := insertRegexp(ctx, db, r)
if err != nil {
return nil, err
}
return rdi.GetByID(ctx, r.ID)
}
// GetByID .
func (rdi *RegexpDaoImpl) GetByID(ctx context.Context, id int64) (*Regexp, error) {
rs, err := rdi.GetByIDs(ctx, []int64{id})
if err != nil {
return nil, err
}
if rs[0] == nil {
return nil, ErrResourceNotExist
}
return rs[0], nil
}
// GetByIDs .
func (*RegexpDaoImpl) GetByIDs(ctx context.Context, ids []int64) ([]*Regexp, error) {
rs, err := queryRegexps(ctx, db, fmt.Sprintf(selectRegexpByIDsSQL, util.IntSliToSQLVarchars(ids)))
if err != nil {
return nil, err
}
res := make([]*Regexp, len(ids))
for i, id := range ids {
for _, r := range rs {
if r.ID == id {
res[i] = r
}
}
}
return res, nil
}
// GetByContents .
func (*RegexpDaoImpl) GetByContents(ctx context.Context, contents []string) ([]*Regexp, error) {
if len(contents) == 0 {
log.Error("%v", ErrParams)
return nil, ErrParams
}
rs, err := queryRegexps(ctx, db, fmt.Sprintf(selectRegexpByContentsSQL, util.StrSliToSQLVarchars(contents)))
if err != nil {
return nil, err
}
res := make([]*Regexp, len(contents))
for i, c := range contents {
for _, r := range rs {
if strings.EqualFold(r.Content, c) {
res[i] = r
}
}
}
return res, nil
}
// GetByAreaAndContent .
func (*RegexpDaoImpl) GetByAreaAndContent(ctx context.Context, cond *Condition) (*Regexp, error) {
rs, err := queryRegexps(ctx, db, fmt.Sprintf(selectRegexpByAreaAndContentSQL,
cond.Area, util.StrSliToSQLVarchars(cond.Contents)))
if err != nil {
return nil, err
}
return rs[0], nil
}
func insertRegexp(ctx context.Context, executer Executer, r *Regexp) error {
res, err := executer.Exec(ctx, insertRegexpSQL,
r.ID,
r.AdminID,
r.Area,
r.Name,
r.Operation,
r.Content,
r.State,
)
if err != nil {
log.Error("%v", err)
return err
}
lastID, err := res.LastInsertId()
if err != nil {
log.Error("%v", err)
return err
}
r.ID = lastID
return nil
}
func updateRegexp(ctx context.Context, executer Executer, r *Regexp) error {
_, err := executer.Exec(ctx, updateRegexpSQL,
r.AdminID,
r.Name,
r.Content,
r.Operation,
r.State,
time.Now(),
r.ID,
)
if err != nil {
log.Error("%v", err)
return err
}
return nil
}
func queryRegexps(ctx context.Context, q Querier, rawSQL string) ([]*Regexp, error) {
rows, err := q.Query(ctx, rawSQL)
if err == sql.ErrNoRows {
err = ErrResourceNotExist
}
if err != nil {
log.Error("Error: %v, sql: %s", err, rawSQL)
return nil, err
}
defer rows.Close()
rs, err := mapRowToRegexps(rows)
if err != nil {
return nil, err
}
if len(rs) == 0 {
log.Error("Error: %v, sql: %s", ErrResourceNotExist, rawSQL)
return nil, ErrResourceNotExist
}
return rs, nil
}
func mapRowToRegexps(rows *sql.Rows) (rs []*Regexp, err error) {
rs = make([]*Regexp, 0)
for rows.Next() {
r := Regexp{}
err = rows.Scan(
&r.ID,
&r.AdminID,
&r.Area,
&r.Name,
&r.Operation,
&r.Content,
&r.State,
&r.CTime,
&r.MTime,
)
if err != nil {
log.Error("%v", err)
return nil, err
}
rs = append(rs, &r)
}
if err = rows.Err(); err != nil {
log.Error("%v", err)
return nil, err
}
return rs, nil
}

View File

@@ -0,0 +1,107 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func testRegexpDaoImplGetByCond(t *testing.T) {
var (
c = context.TODO()
cond = &Condition{State: "0"}
)
convey.Convey("GetByCond", t, func(ctx convey.C) {
regexps, totalCounts, err := regdi.GetByCond(c, cond)
ctx.Convey("Then err should be nil.regexps,totalCounts should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(totalCounts, convey.ShouldNotBeNil)
ctx.So(regexps, convey.ShouldNotBeNil)
})
})
}
func testRegexpDaoImplDaoUpdate(t *testing.T) {
var (
c = context.TODO()
r = &Regexp{ID: 1, Name: "name", Area: 1, Content: "test"}
)
convey.Convey("Update", t, func(ctx convey.C) {
p1, err := regdi.Update(c, r)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func testRegexpDaoImplInsert(t *testing.T) {
var (
c = context.TODO()
r = &Regexp{ID: 1, Name: "name", Area: 1, Content: "test"}
)
convey.Convey("Insert", t, func(ctx convey.C) {
p1, err := regdi.Insert(c, r)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func testRegexpDaoImplGetByID(t *testing.T) {
var (
c = context.TODO()
id = int64(1)
)
convey.Convey("GetByID", t, func(ctx convey.C) {
p1, err := regdi.GetByID(c, id)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func testRegexpDaoImplGetByIDs(t *testing.T) {
var (
c = context.TODO()
ids = []int64{1}
)
convey.Convey("RegexpDaoImplGetByIDs", t, func(ctx convey.C) {
p1, err := regdi.GetByIDs(c, ids)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func testRegexpDaoImplGetByContents(t *testing.T) {
var (
c = context.TODO()
contents = []string{"test"}
)
convey.Convey("GetByContents", t, func(ctx convey.C) {
p1, err := regdi.GetByContents(c, contents)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func testRegexpDaoImplGetByAreaAndContent(t *testing.T) {
var (
c = context.TODO()
cond = &Condition{State: "0"}
)
convey.Convey("GetByAreaAndContent", t, func(ctx convey.C) {
p1, err := regdi.GetByAreaAndContent(c, cond)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,270 @@
package dao
import (
"context"
"fmt"
"strings"
"time"
"go-common/app/service/main/antispam/util"
"go-common/library/database/sql"
"go-common/library/log"
)
const (
columnRules = "id, area, limit_type, limit_scope, dur_sec, allowed_counts, ctime, mtime"
selectRuleCountsSQL = `SELECT COUNT(1) FROM rate_limit_rules %s`
selectRulesByCondSQL = `SELECT ` + columnRules + ` FROM rate_limit_rules %s`
selectRuleByIDsSQL = `SELECT ` + columnRules + ` FROM rate_limit_rules WHERE id IN(%s)`
selectRulesByAreaSQL = `SELECT ` + columnRules + ` FROM rate_limit_rules WHERE area = %s`
selectRulesByAreaAndTypeSQL = `SELECT ` + columnRules + ` FROM rate_limit_rules WHERE area = %s AND limit_type = %s`
selectRulesByAreaAndTypeAndScopeSQL = `SELECT ` + columnRules + ` FROM rate_limit_rules WHERE area = %s AND limit_type = %s AND limit_scope = %s`
insertRuleSQL = `INSERT INTO rate_limit_rules(area, limit_type, limit_scope, dur_sec, allowed_counts) VALUES(?, ?, ?, ?, ?)`
updateRuleSQL = `UPDATE rate_limit_rules SET dur_sec = ?, allowed_counts = ?, mtime = ? WHERE area = ? AND limit_type = ? AND limit_scope = ?`
)
// Rule .
type Rule struct {
ID int64 `db:"id"`
Area int `db:"area"`
LimitType int `db:"limit_type"`
LimitScope int `db:"limit_scope"`
DurationSec int64 `db:"dur_sec"`
AllowedCounts int64 `db:"allowed_counts"`
CTime time.Time `db:"ctime"`
MTime time.Time `db:"mtime"`
}
// RuleDaoImpl .
type RuleDaoImpl struct{}
const (
// LimitTypeDefaultLimit .
LimitTypeDefaultLimit int = iota
// LimitTypeRestrictLimit .
LimitTypeRestrictLimit
// LimitTypeWhite .
LimitTypeWhite
// LimitTypeBlack .
LimitTypeBlack
)
const (
// LimitScopeGlobal .
LimitScopeGlobal int = iota
// LimitScopeLocal .
LimitScopeLocal
)
// NewRuleDao .
func NewRuleDao() *RuleDaoImpl {
return &RuleDaoImpl{}
}
func updateRule(ctx context.Context, executer Executer, r *Rule) error {
_, err := executer.Exec(ctx,
updateRuleSQL,
r.DurationSec,
r.AllowedCounts,
time.Now(),
r.Area,
r.LimitType,
r.LimitScope,
)
if err != nil {
log.Error("%v", err)
return err
}
return nil
}
func insertRule(ctx context.Context, executer Executer, r *Rule) error {
res, err := executer.Exec(ctx,
insertRuleSQL,
r.Area,
r.LimitType,
r.LimitScope,
r.DurationSec,
r.AllowedCounts,
)
if err != nil {
log.Error("%v", err)
return err
}
lastID, err := res.LastInsertId()
if err != nil {
log.Error("%v", err)
return err
}
r.ID = lastID
return nil
}
// GetByCond .
func (*RuleDaoImpl) GetByCond(ctx context.Context, cond *Condition) (rules []*Rule, totalCounts int64, err error) {
sqlConds := make([]string, 0)
if cond.Area != "" {
sqlConds = append(sqlConds, fmt.Sprintf("area = %s", cond.Area))
}
if cond.State != "" {
sqlConds = append(sqlConds, fmt.Sprintf("state = %s", cond.State))
}
var optionSQL string
if len(sqlConds) > 0 {
optionSQL = fmt.Sprintf("WHERE %s", strings.Join(sqlConds, " AND "))
}
var limitSQL string
if cond.Pagination != nil {
queryCountsSQL := fmt.Sprintf(selectRuleCountsSQL, optionSQL)
totalCounts, err = GetTotalCounts(ctx, db, queryCountsSQL)
if err != nil {
return nil, 0, err
}
offset, limit := cond.OffsetLimit(totalCounts)
if limit == 0 {
return nil, 0, ErrResourceNotExist
}
limitSQL = fmt.Sprintf("LIMIT %d, %d", offset, limit)
}
if cond.OrderBy != "" {
optionSQL = fmt.Sprintf("%s ORDER BY %s %s", optionSQL, cond.OrderBy, cond.Order)
}
if limitSQL != "" {
optionSQL = fmt.Sprintf("%s %s", optionSQL, limitSQL)
}
querySQL := fmt.Sprintf(selectRulesByCondSQL, optionSQL)
log.Info("OptionSQL(%s), GetByCondSQL(%s)", optionSQL, querySQL)
rules, err = queryRules(ctx, db, querySQL)
if err != nil {
return nil, totalCounts, err
}
return rules, totalCounts, nil
}
// Update .
func (rdi *RuleDaoImpl) Update(ctx context.Context, r *Rule) (*Rule, error) {
if err := updateRule(ctx, db, r); err != nil {
return nil, err
}
return rdi.GetByAreaAndTypeAndScope(ctx, &Condition{
Area: fmt.Sprintf("%d", r.Area),
LimitType: fmt.Sprintf("%d", r.LimitType),
LimitScope: fmt.Sprintf("%d", r.LimitScope),
})
}
// Insert .
func (rdi *RuleDaoImpl) Insert(ctx context.Context, r *Rule) (*Rule, error) {
if err := insertRule(ctx, db, r); err != nil {
return nil, err
}
return rdi.GetByID(ctx, r.ID)
}
// GetByID .
func (rdi *RuleDaoImpl) GetByID(ctx context.Context, id int64) (*Rule, error) {
rs, err := rdi.GetByIDs(ctx, []int64{id})
if err != nil {
return nil, err
}
if rs[0] == nil {
return nil, ErrResourceNotExist
}
return rs[0], nil
}
// GetByIDs .
func (*RuleDaoImpl) GetByIDs(ctx context.Context, ids []int64) ([]*Rule, error) {
rs, err := queryRules(ctx, db, fmt.Sprintf(selectRuleByIDsSQL, util.IntSliToSQLVarchars(ids)))
if err != nil {
return nil, err
}
res := make([]*Rule, len(ids))
for i, id := range ids {
for _, r := range rs {
if r.ID == id {
res[i] = r
}
}
}
return res, nil
}
// GetByAreaAndLimitType .
func (*RuleDaoImpl) GetByAreaAndLimitType(ctx context.Context, cond *Condition) ([]*Rule, error) {
return queryRules(ctx, db, fmt.Sprintf(selectRulesByAreaAndTypeSQL, cond.Area, cond.LimitType))
}
// GetByAreaAndTypeAndScope .
func (*RuleDaoImpl) GetByAreaAndTypeAndScope(ctx context.Context, cond *Condition) (*Rule, error) {
rs, err := queryRules(ctx, db, fmt.Sprintf(selectRulesByAreaAndTypeAndScopeSQL,
cond.Area,
cond.LimitType,
cond.LimitScope,
))
if err != nil {
return nil, err
}
return rs[0], nil
}
// GetByArea .
func (*RuleDaoImpl) GetByArea(ctx context.Context, cond *Condition) ([]*Rule, error) {
return queryRules(ctx, db, fmt.Sprintf(selectRulesByAreaSQL, cond.Area))
}
func queryRules(ctx context.Context, q Querier, rawSQL string) ([]*Rule, error) {
log.Info("Query sql: %q", rawSQL)
rows, err := q.Query(ctx, rawSQL)
if err == sql.ErrNoRows {
err = ErrResourceNotExist
}
if err != nil {
log.Error("Error: %v, RawSQL: %s", err, rawSQL)
return nil, err
}
defer rows.Close()
rs, err := mapRowToRules(rows)
if err != nil {
return nil, err
}
if len(rs) == 0 {
return nil, ErrResourceNotExist
}
return rs, nil
}
func mapRowToRules(rows *sql.Rows) (rs []*Rule, err error) {
for rows.Next() {
r := Rule{}
err = rows.Scan(
&r.ID,
&r.Area,
&r.LimitType,
&r.LimitScope,
&r.DurationSec,
&r.AllowedCounts,
&r.CTime,
&r.MTime,
)
if err != nil {
log.Error("%v", err)
return nil, err
}
rs = append(rs, &r)
}
if err = rows.Err(); err != nil {
log.Error("%v", err)
return nil, err
}
return rs, nil
}

View File

@@ -0,0 +1,121 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func testRuleDaoImplGetByCond(t *testing.T) {
var (
c = context.TODO()
cond = &Condition{}
)
convey.Convey("GetByCond", t, func(ctx convey.C) {
rules, totalCounts, err := rdi.GetByCond(c, cond)
ctx.Convey("Then err should be nil.rules,totalCounts should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(totalCounts, convey.ShouldNotBeNil)
ctx.So(rules, convey.ShouldNotBeNil)
})
})
}
func testRuleDaoImplUpdate(t *testing.T) {
var (
c = context.TODO()
r = &Rule{}
)
convey.Convey("Update", t, func(ctx convey.C) {
p1, err := rdi.Update(c, r)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func testRuleDaoImplInsert(t *testing.T) {
var (
c = context.TODO()
r = &Rule{}
)
convey.Convey("Insert", t, func(ctx convey.C) {
p1, err := rdi.Insert(c, r)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func testRuleDaoImplGetByID(t *testing.T) {
var (
c = context.TODO()
id = int64(0)
)
convey.Convey("GetByID", t, func(ctx convey.C) {
p1, err := rdi.GetByID(c, id)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func testRuleDaoImplDaoGetByIDs(t *testing.T) {
var (
c = context.TODO()
ids = []int64{}
)
convey.Convey("GetByIDs", t, func(ctx convey.C) {
p1, err := rdi.GetByIDs(c, ids)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func testRuleDaoImplGetByAreaAndLimitType(t *testing.T) {
var (
c = context.TODO()
cond = &Condition{}
)
convey.Convey("GetByAreaAndLimitType", t, func(ctx convey.C) {
p1, err := rdi.GetByAreaAndLimitType(c, cond)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func testRuleDaoImplGetByAreaAndTypeAndScope(t *testing.T) {
var (
c = context.TODO()
cond = &Condition{}
)
convey.Convey("GetByAreaAndTypeAndScope", t, func(ctx convey.C) {
p1, err := rdi.GetByAreaAndTypeAndScope(c, cond)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func testRuleDaoImplGetByArea(t *testing.T) {
var (
c = context.TODO()
cond = &Condition{}
)
convey.Convey("GetByArea", t, func(ctx convey.C) {
p1, err := rdi.GetByArea(c, cond)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,48 @@
package dao
/*
import (
"context"
xsql "go-common/database/sql"
)
type TxImpl struct {
*xsql.Tx
}
func NewTx(ctx context.Context) (Tx, error) {
t, err := db.Begin(ctx)
if err != nil {
return nil, err
}
return &TxImpl{t}, nil
}
func (tx *TxImpl) UpdateKeyword(k *Keyword) error {
return updateKeyword(tx.Ctx, tx, k)
}
func (tx *TxImpl) InsertKeyword(k *Keyword) error {
return insertKeyword(tx.Ctx, tx, k)
}
func (tx *TxImpl) InsertRule(r *Rule) error {
return insertRule(tx.Ctx, tx, r)
}
func (tx *TxImpl) UpdateRegexp(r *Regexp) error {
return updateRegexp(tx.Ctx, tx, r)
}
func (tx *TxImpl) InsertRegexp(r *Regexp) error {
return insertRegexp(tx.Ctx, tx, r)
}
func (tx *TxImpl) QueryRow(_ context.Context, sql string, args ...interface{}) *xsql.Row {
return tx.Tx.QueryRow(sql, args)
}
func (tx *TxImpl) Query(_ context.Context, sql string, args ...interface{}) (*xsql.Rows, error) {
return tx.Tx.Query(sql, args)
}*/

View File

@@ -0,0 +1 @@
package dao