Apply .gitignore rules

This commit is contained in:
皮蛋13361098506
2025-01-06 16:21:36 +08:00
parent 1b77f62820
commit ccd2c530cf
580 changed files with 69806 additions and 0 deletions

View File

@@ -0,0 +1,233 @@
/*
未实现的哈希表方法:
MOVE、SCAN、SORT、FLUSHDB、FLUSHALL、SELECT、SWAPDB
*/
package redisUtil
import (
"github.com/gomodule/redigo/redis"
)
/*
EXPIRE key seconds
可用版本: >= 1.0.0
时间复杂度: O(1)
为给定 key 设置生存时间,当 key 过期时(生存时间为 0 ),它会被自动删除。
在 Redis 中,带有生存时间的 key 被称为『易失的』(volatile)。
生存时间可以通过使用 DEL 命令来删除整个 key 来移除,或者被 SET 和 GETSET 命令覆写(overwrite),这意味着,如果一个命令只是修改(alter)一个带生存时间的 key 的值而不是用一个新的 key 值来代替(replace)它的话,那么生存时间不会被改变。
比如说,对一个 key 执行 INCR 命令,对一个列表进行 LPUSH 命令,或者对一个哈希表执行 HSET 命令,这类操作都不会修改 key 本身的生存时间。
另一方面,如果使用 RENAME 对一个 key 进行改名,那么改名后的 key 的生存时间和改名前一样。
RENAME 命令的另一种可能是,尝试将一个带生存时间的 key 改名成另一个带生存时间的 another_key ,这时旧的 another_key (以及它的生存时间)会被删除,然后旧的 key 会改名为 another_key ,因此,新的 another_key 的生存时间也和原本的 key 一样。
使用 PERSIST 命令可以在不删除 key 的情况下,移除 key 的生存时间,让 key 重新成为一个『持久的』(persistent) key 。
更新生存时间
可以对一个已经带有生存时间的 key 执行 EXPIRE 命令,新指定的生存时间会取代旧的生存时间。
过期时间的精确度
在 Redis 2.4 版本中,过期时间的延迟在 1 秒钟之内 —— 也即是,就算 key 已经过期,但它还是可能在过期之后一秒钟之内被访问到,而在新的 Redis 2.6 版本中,延迟被降低到 1 毫秒之内。
Redis 2.1.3 之前的不同之处
在 Redis 2.1.3 之前的版本中,修改一个带有生存时间的 key 会导致整个 key 被删除,这一行为是受当时复制(replication)层的限制而作出的,现在这一限制已经被修复。
返回值
设置成功返回 1 。 当 key 不存在或者不能为 key 设置生存时间时(比如在低于 2.1.3 版本的 Redis 中你尝试更新 key 的生存时间),返回 0 。
*/
func (this *RedisPool) Expire(key string, seconds int64) (successful bool, err error) {
conn := this.GetConnection()
defer conn.Close()
var result int
if result, err = redis.Int(conn.Do("EXPIRE", key, seconds)); err != nil {
return
}
if result == 1 {
successful = true
}
return
}
/*
EXPIREAT key timestamp
可用版本: >= 1.2.0
时间复杂度: O(1)
EXPIREAT 的作用和 EXPIRE 类似,都用于为 key 设置生存时间。
不同在于 EXPIREAT 命令接受的时间参数是 UNIX 时间戳(unix timestamp)。
返回值
如果生存时间设置成功,返回 1 当 key 不存在或没办法设置生存时间,返回 0 。
*/
func (this *RedisPool) ExpireAt(key string, timestamp int64) (successful bool, err error) {
conn := this.GetConnection()
defer conn.Close()
var result int
if result, err = redis.Int(conn.Do("EXPIREAT", key, timestamp)); err != nil {
return
}
if result == 1 {
successful = true
}
return
}
/*
TTL key
可用版本: >= 1.0.0
时间复杂度: O(1)
以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live)。
返回值
当 key 不存在时,返回 -2 。 当 key 存在但没有设置剩余生存时间时,返回 -1 。 否则,以秒为单位,返回 key 的剩余生存时间。
Note
在 Redis 2.8 以前,当 key 不存在,或者 key 没有设置剩余生存时间时,命令都返回 -1 。
*/
func (this *RedisPool) TTL(key string) (ttl int64, exist, persisted bool, err error) {
conn := this.GetConnection()
defer conn.Close()
ttl, err = redis.Int64(conn.Do("TTL", key))
if err != nil {
return
}
if ttl == -2 {
exist = false
persisted = false
} else if ttl == -1 {
exist = true
persisted = true
} else {
exist = true
persisted = false
}
return
}
/*
PERSIST key
可用版本: >= 2.2.0
时间复杂度: O(1)
移除给定 key 的生存时间,将这个 key 从“易失的”(带生存时间 key )转换成“持久的”(一个不带生存时间、永不过期的 key )。
返回值
当生存时间移除成功时,返回 1 . 如果 key 不存在或 key 没有设置生存时间,返回 0 。
*/
func (this *RedisPool) Persist(key string) (successful bool, err error) {
conn := this.GetConnection()
defer conn.Close()
var result int
if result, err = redis.Int(conn.Do("PERSIST", key)); err != nil {
return
}
if result == 1 {
successful = true
}
return
}
/*
PEXPIRE key milliseconds
可用版本: >= 2.6.0
时间复杂度: O(1)
这个命令和 EXPIRE 命令的作用类似,但是它以毫秒为单位设置 key 的生存时间,而不像 EXPIRE 命令那样,以秒为单位。
返回值
设置成功,返回 1 key 不存在或设置失败,返回 0
*/
func (this *RedisPool) PExpire(key string, milliseconds int64) (successful bool, err error) {
conn := this.GetConnection()
defer conn.Close()
var result int
if result, err = redis.Int(conn.Do("PEXPIRE", key, milliseconds)); err != nil {
return
}
if result == 1 {
successful = true
}
return
}
/*
PEXPIREAT key milliseconds-timestamp
可用版本: >= 2.6.0
时间复杂度: O(1)
这个命令和 expireat 命令类似,但它以毫秒为单位设置 key 的过期 unix 时间戳,而不是像 expireat 那样,以秒为单位。
返回值
如果生存时间设置成功,返回 1 。 当 key 不存在或没办法设置生存时间时,返回 0 。(查看 EXPIRE key seconds 命令获取更多信息)
*/
func (this *RedisPool) PExpireAt(key string, milliseconds_timestamp int64) (successful bool, err error) {
conn := this.GetConnection()
defer conn.Close()
var result int
if result, err = redis.Int(conn.Do("PEXPIREAT", key, milliseconds_timestamp)); err != nil {
return
}
if result == 1 {
successful = true
}
return
}
/*
PTTL key
可用版本: >= 2.6.0
复杂度: O(1)
这个命令类似于 TTL 命令,但它以毫秒为单位返回 key 的剩余生存时间,而不是像 TTL 命令那样,以秒为单位。
返回值
当 key 不存在时,返回 -2 。
当 key 存在但没有设置剩余生存时间时,返回 -1 。
否则,以毫秒为单位,返回 key 的剩余生存时间。
Note
在 Redis 2.8 以前,当 key 不存在,或者 key 没有设置剩余生存时间时,命令都返回 -1 。
*/
func (this *RedisPool) PTTL(key string) (pttl int64, exist bool, persisted bool, err error) {
conn := this.GetConnection()
defer conn.Close()
pttl, err = redis.Int64(conn.Do("PTTL", key))
if err != nil {
return
}
if pttl == -2 {
exist = false
persisted = false
} else if pttl == -1 {
exist = true
persisted = true
} else {
exist = true
persisted = false
}
return
}

View File

@@ -0,0 +1,16 @@
#!/bin/bash
# 查找 adminServer 的 PID
PID=$(pgrep adminServer)
if [ -z "$PID" ]; then
echo "adminServer 进程未找到"
else
echo "停止中... (PID: $PID)"
kill $PID
if [ $? -eq 0 ]; then
echo "adminServer 进程已终止 (PID: $PID)"
else
echo "无法终止 adminServer 进程 (PID: $PID)"
fi
fi

View File

@@ -0,0 +1,52 @@
package logUtil
// ILog
// @description: 日志接口
type ILog interface {
// InfoLog
// @description: 信息日志记录
// parameter:
// @format:日志格式
// @args:参数列表
// return:
InfoLog(format string, args ...interface{})
// DebugLog
// @description: 调试日志记录
// parameter:
// @format:日志格式
// @args:参数列表
// return:
DebugLog(format string, args ...interface{})
// WarnLog
// @description: 警告日志记录
// parameter:
// @format:日志格式
// @args:参数列表
// return:
WarnLog(format string, args ...interface{})
// ErrorLog
// @description: 错误日志记录
// parameter:
// @format:日志格式
// @args:参数列表
// return:
ErrorLog(format string, args ...interface{})
// FatalLog
// @description: 致命错误日志记录
// parameter:
// @format:日志格式
// @args:参数列表
// return:
FatalLog(format string, args ...interface{})
// CloseLog
// @description: 关闭日志
// parameter:
// @waitFinish:是否等待日志
// return:
CloseLog(waitFinish bool)
}

View File

@@ -0,0 +1,450 @@
// ************************************
// @package: websocketServer
// @description: websocket管理
// @author:
// @revision history:
// @create date: 2022-02-18 15:38:17
// ************************************
package websocketServer
import (
"errors"
"github.com/gorilla/websocket"
routineCtrlUtil "goutil/routineCtrlUtil"
"sync"
"time"
)
const (
// 默认广播并发数
con_DEFAULT_BROADCAST_CONCURRENT = 10
)
// connManager
// @description: websocket连接管理
type connManager struct {
// 是否禁止新连接
disableNewConn bool
// 广播并发数
broadcastConcurrent int
// websocket服务端配置结构
upgrader *websocket.Upgrader
// 广播锁-限制 消息广播/关闭所有连接 并发访问
muBroadcast sync.Mutex
// 连接池map写锁(增加/删除)
muAllConns sync.Mutex
// 连接池-所有已连接的websocket
allConns map[*websocket.Conn]*Context
//-------------------
// 心跳控制
// 接收到Ping消息时是否自动回复Pong
autuPong bool
// 心跳周期
heartbeatCycle time.Duration
// 断连周期数(超过几个心跳周期即自动关闭连接)设置为0即关闭心跳检测功能
heartbeatCloseCount int
// 是否已开启心跳检测协程
isHeartbeatDetectStart bool
}
// heartbeatDetect
// @description: 开启心跳检测协程
// parameter:
//
// @receiver connMgr:
//
// return:
func (connMgr *connManager) heartbeatDetect() {
// 限制每个websocket连接管理只开启一个心跳检测协程
if !connMgr.isHeartbeatDetectStart {
connMgr.isHeartbeatDetectStart = true
// 开启心跳检测协程
go func() {
for {
if connMgr.heartbeatCloseCount <= 0 {
// 心跳检测功能已关闭;每秒检测此标志
time.Sleep(time.Second)
continue
}
// 心跳检测功能已开启
connMgr.muAllConns.Lock() // 连接池map锁
ctxs_timeout := make([]*Context, 0, len(connMgr.allConns)) // 存放心跳超时需要关闭的websocket环境
for _, ctx := range connMgr.allConns {
if time.Since(ctx.heartbeat) > (connMgr.heartbeatCycle*time.Duration(connMgr.heartbeatCloseCount) + 1) {
// 心跳超时需要关闭的websocket环境加入列表
ctxs_timeout = append(ctxs_timeout, ctx)
}
}
connMgr.muAllConns.Unlock() // 连接池map及时解锁
// 关闭所有心跳超时的连接
func() {
// 获取广播并发数
broadcastConcurrent := connMgr.broadcastConcurrent
if broadcastConcurrent <= 0 {
broadcastConcurrent = con_DEFAULT_BROADCAST_CONCURRENT
}
// 协程并发限制
rtCtrl := routineCtrlUtil.New(broadcastConcurrent)
for _, ctx := range ctxs_timeout {
ctxTemp := ctx
rtCtrl.Run(func(arg interface{}) {
// 执行受限并发函数
ctxTemp.Close()
}, nil)
}
// 等待完成
rtCtrl.Wait()
}()
// 休眠半个心跳周期
slpTime := time.Duration(connMgr.heartbeatCycle / 2)
if slpTime < time.Second {
slpTime = time.Second
}
time.Sleep(slpTime)
}
}()
}
}
// upgrade
// @description: 升级为websocket
// parameter:
//
// @receiver connMgr:
// @ctx: websocket环境
//
// return:
//
// @*websocket.Conn: 建立的连接对象
// @error:
func (connMgr *connManager) upgrade(ctx *Context) (conn *websocket.Conn, err error) {
if connMgr.disableNewConn {
// 禁止新连接
return nil, errors.New("connManager(disableNewConn)")
}
// 建立websocket连接
conn, err = connMgr.upgrader.Upgrade(ctx.GetWebServerContext().GetResponseWriter(), ctx.GetWebServerContext().GetRequest(), nil)
if err != nil {
return
}
// 添加到连接池
ctx.conn = conn
connMgr.addConn(conn, ctx)
return
}
// addConn
// @description: 添加到连接池
// parameter:
//
// @receiver connMgr:
// @conn:
// @ctx:
//
// return:
func (connMgr *connManager) addConn(conn *websocket.Conn, ctx *Context) {
connMgr.muAllConns.Lock()
defer connMgr.muAllConns.Unlock()
connMgr.allConns[conn] = ctx
}
// delConn
// @description: 将连接从连接池删除
// parameter:
//
// @receiver connMgr:
// @conn:
//
// return:
func (connMgr *connManager) delConn(conn *websocket.Conn) {
connMgr.muAllConns.Lock()
defer connMgr.muAllConns.Unlock()
delete(connMgr.allConns, conn)
}
// renewAllConnsMap
// @description: 重新替换一个新allConns的map结构以免被标记删除的冗余信息造成存储和性能问题
// parameter:
//
// @receiver connMgr:
//
// return:
//
// @map[*websocket.Conn]*Context: 返回原内部使用的连接池(现内部已不再使用)
func (connMgr *connManager) renewAllConnsMap() map[*websocket.Conn]*Context {
connMgr.muAllConns.Lock()
defer connMgr.muAllConns.Unlock()
// map拷贝
allConnsCopy := make(map[*websocket.Conn]*Context, len(connMgr.allConns))
for conn, ctx := range connMgr.allConns {
allConnsCopy[conn] = ctx
}
// map替换因map删除时只是标记并非真正删除使用一段时间后可能会出现大量未使用信息这里顺便更新一下map
connMgr.allConns, allConnsCopy = allConnsCopy, connMgr.allConns
return allConnsCopy
}
// SetBroadcastConcurrent
// @description: 设置广播并发数
// parameter:
//
// @receiver connMgr:
// @n: 广播并发数
//
// return:
func (connMgr *connManager) SetBroadcastConcurrent(n int) {
connMgr.broadcastConcurrent = n
}
// EnableNewConn
// @description: 允许新连接
// parameter:
//
// @receiver connMgr:
//
// return:
func (connMgr *connManager) EnableNewConn() {
connMgr.disableNewConn = false
}
// DisableNewConn
// @description: 禁用新连接
// parameter:
//
// @receiver connMgr:
//
// return:
func (connMgr *connManager) DisableNewConn() {
connMgr.disableNewConn = true
}
// MulticastMessage
// @description: 多播消息(给指定多用户发送消息)
// parameter:
//
// @receiver connMgr:
// @ctxs: 指定多用户的*Context切片
// @messageType: websocket类型
// @data: 发送的数据
//
// return:
//
// @err: 若有错误,则为最后一个错误
func (connMgr *connManager) MulticastMessage(ctxs []*Context, messageType int, data []byte) (err error) {
// 广播锁,防重入
connMgr.muBroadcast.Lock()
defer connMgr.muBroadcast.Unlock()
// 获取广播并发数
broadcastConcurrent := connMgr.broadcastConcurrent
if broadcastConcurrent <= 0 {
broadcastConcurrent = con_DEFAULT_BROADCAST_CONCURRENT
}
// 协程并发限制
rtCtrl := routineCtrlUtil.New(broadcastConcurrent)
var mu sync.Mutex
for _, ctx := range ctxs {
// 执行受限并发函数
// 注意这里的ctx需要使用参数传入Run否则随时变化的ctx在闭包内使用时会出现不符合程序要求逻辑的结果
rtCtrl.Run(func(arg interface{}) {
ctxTemp, _ := arg.(*Context)
e := ctxTemp.SendMessage(messageType, data)
if e != nil {
mu.Lock()
err = e
mu.Unlock()
}
}, ctx)
}
// 等待完成
rtCtrl.Wait()
return
}
// BroadcastMessage
// @description: 消息广播
// parameter:
//
// @receiver connMgr:
// @messageType: websocket类型
// @data: 发送的数据
//
// return:
//
// @err: 若有错误,则为最后一个错误
func (connMgr *connManager) BroadcastMessage(messageType int, data []byte) (err error) {
// 广播锁,防重入
connMgr.muBroadcast.Lock()
defer connMgr.muBroadcast.Unlock()
// 重新替换一个新allConns的map结构以免被标记删除的冗余信息造成存储和性能问题
allConnsCopy := connMgr.renewAllConnsMap()
// 获取广播并发数
broadcastConcurrent := connMgr.broadcastConcurrent
if broadcastConcurrent <= 0 {
broadcastConcurrent = con_DEFAULT_BROADCAST_CONCURRENT
}
// 协程并发限制
rtCtrl := routineCtrlUtil.New(broadcastConcurrent)
var mu sync.Mutex
for _, ctx := range allConnsCopy {
// 执行受限并发函数
// 注意这里的ctx需要使用参数传入Run否则随时变化的ctx在闭包内使用时会出现不符合程序要求逻辑的结果
rtCtrl.Run(func(arg interface{}) {
ctxTemp, _ := arg.(*Context)
e := ctxTemp.SendMessage(messageType, data)
if e != nil {
mu.Lock()
err = e
mu.Unlock()
}
}, ctx)
}
// 等待完成
rtCtrl.Wait()
return
}
// CloseAll
// @description: 关闭所有连接
// parameter:
//
// @receiver connMgr:
//
// return:
func (connMgr *connManager) CloseAll() {
// 广播锁,防重入
connMgr.muBroadcast.Lock()
defer connMgr.muBroadcast.Unlock()
// 重新替换一个新allConns的map结构以免被标记删除的冗余信息造成存储和性能问题
allConnsCopy := connMgr.renewAllConnsMap()
// 获取广播并发数
broadcastConcurrent := connMgr.broadcastConcurrent
if broadcastConcurrent <= 0 {
broadcastConcurrent = con_DEFAULT_BROADCAST_CONCURRENT
}
// 协程并发限制
rtCtrl := routineCtrlUtil.New(broadcastConcurrent)
for _, ctx := range allConnsCopy {
rtCtrl.Run(func(arg interface{}) {
ctxTemp, _ := arg.(*Context)
// 执行受限并发函数
ctxTemp.Close()
}, ctx)
}
// 等待完成
rtCtrl.Wait()
}
// SetUpgrader
// @description: 设置websocket参数结构
// parameter:
//
// @receiver connMgr:
// @upgrader: websocket中的websocket.Upgrader结构体指针可以设置握手超时/读写缓存/是否允许跨域等)
//
// return:
func (connMgr *connManager) SetUpgrader(upgrader *websocket.Upgrader) {
connMgr.upgrader = upgrader
}
// GetUpgrader
// @description: 获取websocket参数结构
// parameter:
//
// @receiver connMgr:
//
// return:
//
// @*websocket.Upgrader: websocket中的websocket.Upgrader结构体指针可以设置握手超时/读写缓存/是否允许跨域等)
func (connMgr *connManager) GetUpgrader() *websocket.Upgrader {
return connMgr.upgrader
}
// SetAutoPong
// @description: 设置接收到Ping消息时是否自动回复Pong信息
// parameter:
//
// @receiver connMgr:
// @autuPong:
//
// return:
func (connMgr *connManager) SetAutoPong(autuPong bool) {
connMgr.autuPong = autuPong
}
// GetAutoPong
// @description: 获取接收到Ping消息时是否自动回复Pong信息
// parameter:
//
// @receiver connMgr:
//
// return:
//
// @bool:
func (connMgr *connManager) GetAutoPong() bool {
return connMgr.autuPong
}
// SetHeartbeatDetectInfo
// @description: 设置心跳检测信息
// parameter:
//
// @receiver connMgr:
// @heartbeatCloseCount: 断连周期数(超过几个心跳周期即自动关闭连接)设置为0即关闭心跳检测功能
// @heartbeatCycle: 心跳周期
//
// return:
func (connMgr *connManager) SetHeartbeatDetectInfo(heartbeatCloseCount int, heartbeatCycle time.Duration) {
connMgr.heartbeatCycle = heartbeatCycle
connMgr.heartbeatCloseCount = heartbeatCloseCount
}
// GetHeartbeatDetectInfo
// @description: 获取心跳检测信息
// parameter:
//
// @receiver connMgr:
//
// return:
//
// @heartbeatCloseCount: 断连周期数(超过几个心跳周期即自动关闭连接)
// @heartbeatCycle: 心跳周期
func (connMgr *connManager) GetHeartbeatDetectInfo() (heartbeatCloseCount int, heartbeatCycle time.Duration) {
return connMgr.heartbeatCloseCount, connMgr.heartbeatCycle
}

View File

@@ -0,0 +1,46 @@
package user
import (
"common/connection"
"goutil/logUtilPlus"
)
// AddUser 添加用户
// AddUser 添加新的用户到数据库中。
// 参数 User: 包含用户信息的对象。
// 返回值: 插入操作影响的行数和可能发生的错误。
func AddUser(User *User) (int64, error) {
//处理一些验证
// 写入到数据库
result := connection.GetUserDB().Create(&User) // 通过数据的指针来创建
if result.Error != nil {
logUtilPlus.ErrorLog("添加用户失败 错误信息:", result.Error.Error())
}
return User.ID, nil
}
// GetUserByID 根据用户ID获取用户信息
func GetUserByID(UserID int64) (*User, error) {
var User User
//缓存判断等一些设置
result := connection.GetUserDB().First(&User, UserID)
if result.Error != nil {
return nil, result.Error
}
return &User, nil
}
// 用户登录
func Login(account string, password string) (*User, error) {
var User User
result := connection.GetUserDB().Where("account = ? AND password = ?", account, password).First(&User)
if result.Error != nil {
return nil, result.Error
}
return &User, nil
}

View File

@@ -0,0 +1,70 @@
package intAndBytesUtil
import (
"encoding/binary"
"testing"
)
func TestBytesToInt(t *testing.T) {
var givenBigEndian []byte = []byte{0, 0, 1, 0}
var givenLittleEndian []byte = []byte{0, 1, 0, 0}
var expectedInt int32 = 256
result := BytesToInt32(givenBigEndian, binary.BigEndian)
if result != expectedInt {
t.Errorf("BytesToInt(%v) failed.Got %v, expected %v", givenBigEndian, result, expectedInt)
}
result = BytesToInt32(givenLittleEndian, binary.LittleEndian)
if result != expectedInt {
t.Errorf("BytesToInt(%v) failed.Got %v, expected %v", givenLittleEndian, result, expectedInt)
}
}
func TestBytesToInt16(t *testing.T) {
var givenBigEndian []byte = []byte{1, 0}
var givenLittleEndian []byte = []byte{0, 1}
var expectedInt int16 = 256
result := BytesToInt16(givenBigEndian, binary.BigEndian)
if result != expectedInt {
t.Errorf("BytesToInt(%v) failed.Got %v, expected %v", givenBigEndian, result, expectedInt)
}
result = BytesToInt16(givenLittleEndian, binary.LittleEndian)
if result != expectedInt {
t.Errorf("BytesToInt(%v) failed.Got %v, expected %v", givenLittleEndian, result, expectedInt)
}
}
func TestBytesToInt32(t *testing.T) {
var givenBigEndian []byte = []byte{0, 0, 1, 0}
var givenLittleEndian []byte = []byte{0, 1, 0, 0}
var expectedInt int32 = 256
result := BytesToInt32(givenBigEndian, binary.BigEndian)
if result != expectedInt {
t.Errorf("BytesToInt(%v) failed.Got %v, expected %v", givenBigEndian, result, expectedInt)
}
result = BytesToInt32(givenLittleEndian, binary.LittleEndian)
if result != expectedInt {
t.Errorf("BytesToInt(%v) failed.Got %v, expected %v", givenLittleEndian, result, expectedInt)
}
}
func TestBytesToInt64(t *testing.T) {
var givenBigEndian []byte = []byte{0, 0, 0, 0, 0, 0, 1, 0}
var givenLittleEndian []byte = []byte{0, 1, 0, 0, 0, 0, 0, 0}
var expectedInt int64 = 256
result := BytesToInt64(givenBigEndian, binary.BigEndian)
if result != expectedInt {
t.Errorf("BytesToInt(%v) failed.Got %v, expected %v", givenBigEndian, result, expectedInt)
}
result = BytesToInt64(givenLittleEndian, binary.LittleEndian)
if result != expectedInt {
t.Errorf("BytesToInt(%v) failed.Got %v, expected %v", givenLittleEndian, result, expectedInt)
}
}

View File

@@ -0,0 +1,95 @@
package ensureSendUtil
import (
"fmt"
"net"
"testing"
"time"
"goutil/debugUtil"
"goutil/zlibUtil"
)
// 保存接收的数据用于校验
var tcp_recv_msg = make([]byte, 0)
func init() {
debugUtil.SetDebug(true)
}
// 创建socket服务器保存收到的数据
func server(addr string) net.Listener {
listener, err := net.Listen("tcp", addr)
if err != nil {
panic(err)
}
go func() {
for {
conn, err := listener.Accept()
if err != nil {
return
}
for {
buff := make([]byte, 512)
_, err := conn.Read(buff)
if err != nil {
break
} else {
decompressed, err := zlibUtil.Decompress(buff[4:])
if err != nil {
panic(err)
} else {
tcp_recv_msg = append(tcp_recv_msg, decompressed...)
}
}
}
}
}()
return listener
}
func Test_tcp(t *testing.T) {
// 开启服务器
l := server("127.0.0.1:9559")
tcp, err := NewTCPSender("./test_tcp", "127.0.0.1:9559")
if err != nil {
t.Error(err)
}
// 发送消息
tcp.Write("tcp-msg-1")
time.Sleep(time.Millisecond * 50) // 等待协程发送数据
// 关闭连接和服务器
l.Close()
(tcp.(*tcpSender)).conn.Close()
// 发送消息,此数据会失败
tcp.Write("tcp-msg-2")
// time.Sleep(time.Millisecond * 50)
// 保存数据
tcp.Close()
// 重启检查是否重发tcp-msg-2
l = server("127.0.0.1:9559")
tcp, err = NewTCPSender("./test_tcp", "127.0.0.1:9559")
if err != nil {
t.Error(err)
}
time.Sleep(time.Second * 2)
if string(tcp_recv_msg) != "tcp-msg-1tcp-msg-2" {
t.Error("message error. got " + string(tcp_recv_msg))
} else {
fmt.Println("TCP OK")
}
tcp.Close()
l.Close()
}

View File

@@ -0,0 +1,35 @@
package esLogUtil
import (
"testing"
"time"
)
func TestWrite(t *testing.T) {
Start("http://10.1.0.86:9200", "dzg_gs_log_gmc2", 20008)
for i := 0; i < 10000; i++ {
InfoLog("ES在线日志测试")
WarnLog("ES在线日志测试")
DebugLog("ES在线日志测试")
ErrorLog("ES在线日志测试")
FatalLog("ES在线日志测试")
}
Stop()
}
func BenchmarkWrite(b *testing.B) {
Start("http://106.52.100.147:14001", "20008_gs_log", 20008)
b.ResetTimer()
for i := 0; i < b.N; i++ {
InfoLog("ES在线日志测试%d", i)
WarnLog("ES在线日志测试%d", i)
DebugLog("ES在线日志测试%d", i)
ErrorLog("ES在线日志测试%d", i)
FatalLog("ES在线日志测试%d", i)
}
b.StopTimer()
time.Sleep(30 * time.Second)
Stop()
}