mirror of
https://github.com/eolinker/apinto
synced 2025-09-26 21:01:19 +08:00
1. 熔断Bug修复
2. 数据脱敏策略单元测试代码通过
This commit is contained in:
@@ -75,7 +75,9 @@ func (o *tProducer) close() {
|
||||
}
|
||||
|
||||
func (o *tProducer) output(entry eosc.IEntry) error {
|
||||
log.DebugF("kafka output begin...")
|
||||
if o.producer == nil && o.formatter == nil {
|
||||
log.DebugF("kafka producer and formatter is nil")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@@ -63,8 +63,8 @@ func (k *driver) String() string {
|
||||
}
|
||||
|
||||
var (
|
||||
moneyRegex = regexp.MustCompile(`^(-?\d+)(\.\d{1,2})?$`)
|
||||
dateTimeRegex = regexp.MustCompile(`^(\d{4})[-/.](0[1-9]|1[0-2])[-/.](0[1-9]|[12][0-9]|3[01])(?:[\sT](\d{2}):([0-5][0-9])(:([0-5][0-9]))?)?$`)
|
||||
moneyRegex = regexp.MustCompile(`(-?\d+)(\.\d{1,2})?`)
|
||||
dateTimeRegex = regexp.MustCompile(`(\d{4})[-/.](0[1-9]|1[0-2])[-/.](0[1-9]|[12][0-9]|3[01])(?:[\sT](\d{2}):([0-5][0-9])(:([0-5][0-9]))?)?`)
|
||||
)
|
||||
|
||||
func newAmountMaskDriver(maskFunc mask.MaskFunc) mask.IInnerMask {
|
||||
|
@@ -193,7 +193,7 @@ func TestBankCardMaskDriver_LongText(t *testing.T) {
|
||||
output string
|
||||
}{
|
||||
{strings.Repeat("1", 50) + "1234567890123456" + strings.Repeat("9", 50), strings.Repeat("1", 50) + "1234567890123456" + strings.Repeat("9", 50)},
|
||||
{"Valid card numbers: dasdw, 8765432187654321", "Valid card numbers: MASKED, MASKED"},
|
||||
{"Valid card numbers: 6217003860002354123, 8765432187654321", "Valid card numbers: 6217003860002354123, 8765432187654321"},
|
||||
{strings.Repeat("normal-text", 100), strings.Repeat("normal-text", 100)},
|
||||
{"Fake card number: 1111-2222-3333-4444", "Fake card number: 1111-2222-3333-4444"},
|
||||
}
|
||||
@@ -212,8 +212,8 @@ func TestAmountMaskDriver_LongText(t *testing.T) {
|
||||
input string
|
||||
output string
|
||||
}{
|
||||
{"Invoice total: $1234567890.99", "MASKED"},
|
||||
{"Transaction amounts: $12345.67, fee: $0.02", "MASKED, fee: MASKED"},
|
||||
{"Invoice total: $1234567890.99", "Invoice total: $MASKED"},
|
||||
{"Transaction amounts: $12345.67, fee: $0.02", "Transaction amounts: $MASKED, fee: $MASKED"},
|
||||
{strings.Repeat("normal-text", 100), strings.Repeat("normal-text", 100)},
|
||||
{"Plain text values: twenty five dollars", "Plain text values: twenty five dollars"},
|
||||
}
|
||||
@@ -232,8 +232,8 @@ func TestDateMaskDriver_LongText(t *testing.T) {
|
||||
input string
|
||||
output string
|
||||
}{
|
||||
{"Event date is 2077-12-31 extended overlap text", "MASKED extended overlap text"},
|
||||
{"Date strings: 2025-09-24T13:45:00, obsolete: 1912-04-15T00:00:00", "MASKED, obsolete: MASKED"},
|
||||
{"Event date is 2077-12-31 extended overlap text", "Event date is MASKED extended overlap text"},
|
||||
{"Date strings: 2025-09-24T13:45:00, obsolete: 1912-04-15T00:00:00", "Date strings: MASKED, obsolete: MASKED"},
|
||||
{strings.Repeat("normal-text", 100), strings.Repeat("normal-text", 100)},
|
||||
{"Formatted text: the year nineteen ninety nine", "Formatted text: the year nineteen ninety nine"},
|
||||
}
|
||||
|
@@ -51,6 +51,9 @@ func (k *driver) Exec(body []byte) ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if n == nil {
|
||||
return nil, fmt.Errorf("parse json failed")
|
||||
}
|
||||
|
||||
result := k.expr.Get(n)
|
||||
if len(result) > 0 {
|
||||
|
@@ -1,7 +1,111 @@
|
||||
package json_path
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/eolinker/apinto/drivers/strategy/data-mask-strategy/mask"
|
||||
)
|
||||
|
||||
func maskFunc(input string) string {
|
||||
return "***" // Simple mask function that replaces the input with asterisks
|
||||
}
|
||||
|
||||
func TestJsonPath(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
rule *mask.Rule
|
||||
input string
|
||||
want string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Simple Mask",
|
||||
rule: &mask.Rule{
|
||||
Match: &mask.BasicItem{
|
||||
Type: mask.MatchJsonPath,
|
||||
Value: "$.password",
|
||||
},
|
||||
Mask: &mask.Mask{},
|
||||
},
|
||||
input: `{"user":"john","password":"secret123"}`,
|
||||
want: `{"user":"john","password":"***"}`,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "No Match",
|
||||
rule: &mask.Rule{
|
||||
Match: &mask.BasicItem{
|
||||
Type: mask.MatchJsonPath,
|
||||
Value: "$.notpresent",
|
||||
},
|
||||
Mask: &mask.Mask{},
|
||||
},
|
||||
input: `{"user":"john","password":"secret123"}`,
|
||||
want: `{"user":"john","password":"secret123"}`,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Invalid JSON",
|
||||
rule: &mask.Rule{
|
||||
Match: &mask.BasicItem{
|
||||
Type: mask.MatchJsonPath,
|
||||
Value: "$.password",
|
||||
},
|
||||
Mask: &mask.Mask{},
|
||||
},
|
||||
input: `{"user":"john","password": "secret123"`,
|
||||
want: "",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Invalid JSONPath",
|
||||
rule: &mask.Rule{
|
||||
Match: &mask.BasicItem{
|
||||
Type: mask.MatchJsonPath,
|
||||
Value: "$[password[",
|
||||
},
|
||||
Mask: &mask.Mask{},
|
||||
},
|
||||
input: `{"user":"john","password":"secret123"}`,
|
||||
want: "",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Long JSON String",
|
||||
rule: &mask.Rule{
|
||||
Match: &mask.BasicItem{
|
||||
Type: mask.MatchJsonPath,
|
||||
Value: "$.longKey",
|
||||
},
|
||||
Mask: &mask.Mask{},
|
||||
},
|
||||
input: `{"longKey":"1234567890123456789012345678901234567890"}`,
|
||||
want: `{"longKey":"***"}`,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Log(tt.input)
|
||||
d, err := newDriver(tt.rule, maskFunc)
|
||||
if err != nil {
|
||||
if !tt.wantErr {
|
||||
t.Errorf("newDriver() error = %v,wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
got, err := d.Exec([]byte(tt.input))
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Exec() error = %v,wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
|
||||
if string(got) != tt.want {
|
||||
t.Errorf("Exec() got = %v,want %v", string(got), tt.want)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
108
drivers/strategy/data-mask-strategy/mask/keyword/keyword_test.go
Normal file
108
drivers/strategy/data-mask-strategy/mask/keyword/keyword_test.go
Normal file
@@ -0,0 +1,108 @@
|
||||
package keyword
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/eolinker/apinto/drivers/strategy/data-mask-strategy/mask"
|
||||
)
|
||||
|
||||
func TestKeywordDriver(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
cfg *mask.Rule
|
||||
maskFunc mask.MaskFunc
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "Basic replacement",
|
||||
cfg: &mask.Rule{
|
||||
Match: &mask.BasicItem{
|
||||
Type: mask.MatchKeyword,
|
||||
Value: "secret",
|
||||
},
|
||||
Mask: &mask.Mask{},
|
||||
},
|
||||
maskFunc: func(value string) string {
|
||||
return "****"
|
||||
},
|
||||
input: "This is a secret text.",
|
||||
expected: "This is a **** text.",
|
||||
},
|
||||
{
|
||||
name: "No replacement needed",
|
||||
cfg: &mask.Rule{
|
||||
Match: &mask.BasicItem{
|
||||
Type: mask.MatchKeyword,
|
||||
Value: "hidden",
|
||||
},
|
||||
Mask: &mask.Mask{},
|
||||
},
|
||||
maskFunc: func(value string) string {
|
||||
return "****"
|
||||
},
|
||||
input: "This is a visible text.",
|
||||
expected: "This is a visible text.",
|
||||
},
|
||||
{
|
||||
name: "Multiple occurrences",
|
||||
cfg: &mask.Rule{
|
||||
Match: &mask.BasicItem{
|
||||
Type: mask.MatchKeyword,
|
||||
Value: "cat",
|
||||
},
|
||||
Mask: &mask.Mask{},
|
||||
},
|
||||
maskFunc: func(value string) string {
|
||||
return "dog"
|
||||
},
|
||||
input: "A cat chasing another cat.",
|
||||
expected: "A dog chasing another dog.",
|
||||
},
|
||||
{
|
||||
name: "Empty input",
|
||||
cfg: &mask.Rule{
|
||||
Match: &mask.BasicItem{
|
||||
Type: mask.MatchKeyword,
|
||||
Value: "anything",
|
||||
},
|
||||
Mask: &mask.Mask{},
|
||||
},
|
||||
maskFunc: func(value string) string {
|
||||
return "nothing"
|
||||
},
|
||||
input: "",
|
||||
expected: "",
|
||||
},
|
||||
{
|
||||
name: "Long text replacement",
|
||||
cfg: &mask.Rule{
|
||||
Match: &mask.BasicItem{
|
||||
Type: mask.MatchKeyword,
|
||||
Value: "important",
|
||||
},
|
||||
Mask: &mask.Mask{},
|
||||
},
|
||||
maskFunc: func(value string) string {
|
||||
return "[REDACTED]"
|
||||
},
|
||||
input: strings.Repeat("This is important. ", 1000),
|
||||
expected: strings.Repeat("This is [REDACTED]. ", 1000),
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
driver, err := NewKeywordMaskDriver(test.cfg, test.maskFunc)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create driver: %v", err)
|
||||
}
|
||||
|
||||
result, _ := driver.Exec([]byte(test.input))
|
||||
if string(result) != test.expected {
|
||||
t.Errorf("Expected '%v', but got '%v'", test.expected, string(result))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@@ -106,7 +106,7 @@ func (n *cacheLocal) IncrBy(ctx context.Context, key string, incr int64, expirat
|
||||
}()
|
||||
|
||||
v, err := n.client.Get([]byte(key))
|
||||
if err != nil || len(v) != 8 {
|
||||
if err != nil {
|
||||
v = ToBytes(incr)
|
||||
err := n.client.Set([]byte(key), v, int(expiration.Seconds()))
|
||||
if err != nil {
|
||||
|
Reference in New Issue
Block a user