199 lines
7.0 KiB
Go
199 lines
7.0 KiB
Go
package worker
|
|
|
|
import (
|
|
"context"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/gogf/gf/v2/frame/g"
|
|
"github.com/gogf/gf/v2/os/gcfg"
|
|
)
|
|
|
|
func TestLoadMonthlyUsageTemplateQPS(t *testing.T) {
|
|
oldAdapter := g.Cfg().GetAdapter()
|
|
adapter, err := gcfg.NewAdapterContent(`
|
|
trafficUsageFullSync:
|
|
consumer:
|
|
templateQPS:
|
|
sim_yd_v5: 30
|
|
sim_dx_v1: 25
|
|
qibin_direct: 1.5
|
|
`)
|
|
if err != nil {
|
|
t.Fatalf("create config adapter: %v", err)
|
|
}
|
|
g.Cfg().SetAdapter(adapter)
|
|
defer g.Cfg().SetAdapter(oldAdapter)
|
|
|
|
got := loadMonthlyUsageTemplateQPS(context.Background())
|
|
if got["sim_yd_v5"] != 30 || got["sim_dx_v1"] != 25 || got["qibin_direct"] != 1.5 {
|
|
t.Fatalf("template QPS = %#v, want configured values", got)
|
|
}
|
|
}
|
|
|
|
func TestLoadSimStatusRunPrefix(t *testing.T) {
|
|
oldAdapter := g.Cfg().GetAdapter()
|
|
defer g.Cfg().SetAdapter(oldAdapter)
|
|
for _, test := range []struct {
|
|
name, config, want string
|
|
invalid bool
|
|
}{
|
|
{"default", "simStatusQueueSync:\n enabled: true\n", "sim-status:", false},
|
|
{"custom", "simStatusQueueSync:\n redisKeyPrefix: 'status:'", "status:", false},
|
|
{"empty", "simStatusQueueSync:\n redisKeyPrefix: ''", "", true},
|
|
} {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
adapter, err := gcfg.NewAdapterContent(test.config)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
g.Cfg().SetAdapter(adapter)
|
|
got, err := loadSimStatusRunPrefix(context.Background())
|
|
if got != test.want || (err != nil) != test.invalid {
|
|
t.Fatalf("prefix=%q err=%v", got, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestLoadDailyUsageTemplateQPS(t *testing.T) {
|
|
oldAdapter := g.Cfg().GetAdapter()
|
|
adapter, err := gcfg.NewAdapterContent(`
|
|
trafficUsageDailySync:
|
|
consumer:
|
|
templateQPS:
|
|
sim_yd_v5: 30
|
|
sim_dx_v1: 25
|
|
`)
|
|
if err != nil {
|
|
t.Fatalf("create config adapter: %v", err)
|
|
}
|
|
g.Cfg().SetAdapter(adapter)
|
|
defer g.Cfg().SetAdapter(oldAdapter)
|
|
|
|
got := loadDailyUsageTemplateQPS(context.Background())
|
|
if got["sim_yd_v5"] != 30 || got["sim_dx_v1"] != 25 {
|
|
t.Fatalf("daily usage template QPS = %#v, want the daily-configured values", got)
|
|
}
|
|
// The daily chain must not silently inherit the monthly chain's rates; the
|
|
// two run against the same carrier quota and must be tuned independently.
|
|
monthly := loadMonthlyUsageTemplateQPS(context.Background())
|
|
if len(monthly) != 0 {
|
|
t.Fatalf("monthly template QPS = %#v, want it unaffected by the daily block", monthly)
|
|
}
|
|
}
|
|
|
|
func TestLoadDailyUsageRunPrefix(t *testing.T) {
|
|
oldAdapter := g.Cfg().GetAdapter()
|
|
defer g.Cfg().SetAdapter(oldAdapter)
|
|
for _, test := range []struct {
|
|
name, config, want string
|
|
invalid bool
|
|
}{
|
|
{"default", "trafficUsageDailySync:\n enabled: true\n", "daily:", false},
|
|
{"custom", "trafficUsageDailySync:\n redisKeyPrefix: 'daily-usage:'", "daily-usage:", false},
|
|
{"empty", "trafficUsageDailySync:\n redisKeyPrefix: ''", "", true},
|
|
} {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
adapter, err := gcfg.NewAdapterContent(test.config)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
g.Cfg().SetAdapter(adapter)
|
|
got, err := loadDailyUsageRunPrefix(context.Background())
|
|
if got != test.want || (err != nil) != test.invalid {
|
|
t.Fatalf("prefix=%q err=%v", got, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestLoadMonthlyHistoryRunPrefix(t *testing.T) {
|
|
oldAdapter := g.Cfg().GetAdapter()
|
|
defer g.Cfg().SetAdapter(oldAdapter)
|
|
for _, test := range []struct {
|
|
name, config, want string
|
|
invalid bool
|
|
}{
|
|
{"default", "trafficUsageMonthlyHistorySync:\n enabled: true\n", "monthly-history:", false},
|
|
{"custom", "trafficUsageMonthlyHistorySync:\n redisKeyPrefix: 'mh:'", "mh:", false},
|
|
{"empty", "trafficUsageMonthlyHistorySync:\n redisKeyPrefix: ''", "", true},
|
|
} {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
adapter, err := gcfg.NewAdapterContent(test.config)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
g.Cfg().SetAdapter(adapter)
|
|
got, err := loadMonthlyHistoryRunPrefix(context.Background())
|
|
if got != test.want || (err != nil) != test.invalid {
|
|
t.Fatalf("prefix=%q err=%v", got, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestMonthlyHistoryPrefixIsIsolatedFromCurrentMonthSync pins the separation of
|
|
// the two monthly chains: trafficUsageFullSync fills the MySQL current-month
|
|
// snapshot, while trafficUsageMonthlyHistorySync fills the TDengine monthly
|
|
// table. Sharing a prefix would let one chain's producer lock block the other.
|
|
func TestMonthlyHistoryPrefixIsIsolatedFromCurrentMonthSync(t *testing.T) {
|
|
oldAdapter := g.Cfg().GetAdapter()
|
|
defer g.Cfg().SetAdapter(oldAdapter)
|
|
adapter, err := gcfg.NewAdapterContent(`
|
|
trafficUsageFullSync:
|
|
redisKeyPrefix: 'flow:'
|
|
trafficUsageMonthlyHistorySync:
|
|
redisKeyPrefix: 'monthly-history:'
|
|
`)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
g.Cfg().SetAdapter(adapter)
|
|
prefixes, err := loadFullSyncArchivePrefixes(context.Background())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
seen := map[string]bool{}
|
|
for _, p := range prefixes {
|
|
seen[p] = true
|
|
}
|
|
if !seen["flow:"] || !seen["monthly-history:"] {
|
|
t.Fatalf("prefixes=%q, want both the current-month and monthly-history chains present", prefixes)
|
|
}
|
|
}
|
|
|
|
func TestLoadFullSyncArchivePrefixes(t *testing.T) {
|
|
oldAdapter := g.Cfg().GetAdapter()
|
|
defer g.Cfg().SetAdapter(oldAdapter)
|
|
for _, test := range []struct {
|
|
name, config string
|
|
want []string
|
|
}{
|
|
{"defaults", "{}", []string{"flow:", "sim-status:", "daily:", "monthly-history:", "imei:"}},
|
|
{"disabled IMEI remains visible", "imeiFullSync:\n enabled: false", []string{"flow:", "sim-status:", "daily:", "monthly-history:", "imei:"}},
|
|
{"custom", "trafficUsageFullSync:\n redisKeyPrefix: 'usage:'\nsimStatusQueueSync:\n redisKeyPrefix: 'status:'\ntrafficUsageDailySync:\n redisKeyPrefix: 'daily-usage:'\ntrafficUsageMonthlyHistorySync:\n redisKeyPrefix: 'monthly-history:'\nimeiFullSync:\n redisKeyPrefix: 'imei-usage:'", []string{"usage:", "status:", "daily-usage:", "monthly-history:", "imei-usage:"}},
|
|
// Duplicate prefixes would make Catalog and SimpleReplay read the same
|
|
// run hash twice, so the list is deduplicated with the first occurrence
|
|
// keeping its position.
|
|
{"shared prefix", "trafficUsageFullSync:\n redisKeyPrefix: 'sync:'\nsimStatusQueueSync:\n redisKeyPrefix: 'sync:'\ntrafficUsageDailySync:\n redisKeyPrefix: 'sync:'\ntrafficUsageMonthlyHistorySync:\n redisKeyPrefix: 'sync:'\nimeiFullSync:\n redisKeyPrefix: 'sync:'", []string{"sync:"}},
|
|
{"daily shares the status prefix", "simStatusQueueSync:\n redisKeyPrefix: 'daily:'\ntrafficUsageDailySync:\n redisKeyPrefix: 'daily:'", []string{"flow:", "daily:", "monthly-history:", "imei:"}},
|
|
{"monthly history shares the daily prefix", "trafficUsageDailySync:\n redisKeyPrefix: 'usage:'\ntrafficUsageMonthlyHistorySync:\n redisKeyPrefix: 'usage:'", []string{"flow:", "sim-status:", "usage:", "imei:"}},
|
|
} {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
adapter, err := gcfg.NewAdapterContent(test.config)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
g.Cfg().SetAdapter(adapter)
|
|
got, err := loadFullSyncArchivePrefixes(context.Background())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !reflect.DeepEqual(got, test.want) {
|
|
t.Fatalf("prefixes=%q, want %q", got, test.want)
|
|
}
|
|
})
|
|
}
|
|
}
|