Like Prometheus, but for logs.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
loki/pkg/util/validation/limits_test.go

319 lines
7.8 KiB

package validation
import (
"testing"
"time"
"github.com/stretchr/testify/require"
)
// nolint:goconst
func TestSmallestPositiveIntPerTenant(t *testing.T) {
type args struct {
tenantIDs []string
f func(string) int
}
tests := []struct {
name string
args args
want int
}{
{
name: "smallest positive int per tenant",
args: args{
tenantIDs: []string{"tenant1", "tenantTwo", "tenantThree"},
f: func(tenantID string) int {
// For ease of testing just pick three unique values representing per-tenant limits
return len(tenantID)
},
},
want: 7, // The smallest of the three
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := SmallestPositiveIntPerTenant(tt.args.tenantIDs, tt.args.f); got != tt.want {
t.Errorf("SmallestPositiveIntPerTenant() = %v, want %v", got, tt.want)
}
})
}
}
// nolint:goconst
func TestSmallestPositiveNonZeroIntPerTenant(t *testing.T) {
type args struct {
tenantIDs []string
f func(string) int
}
tests := []struct {
name string
args args
want int
}{
{
name: "smallest positive non-zero int per tenant",
args: args{
tenantIDs: []string{"tenant1", "tenantTwo", "tenantThree"},
f: func(tenantID string) int {
// For ease of testing just pick three unique values representing per-tenant limits
switch tenantID {
case "tenant1":
return 1
case "tenantTwo":
return 0
case "tenantThree":
return 2
default:
return len(tenantID)
}
},
},
want: 1, // The smallest non-zero of the three
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := SmallestPositiveNonZeroIntPerTenant(tt.args.tenantIDs, tt.args.f); got != tt.want {
t.Errorf("SmallestPositiveNonZeroIntPerTenant() = %v, want %v", got, tt.want)
}
})
}
}
// nolint:goconst
func TestSmallestPositiveNonZeroDurationPerTenant(t *testing.T) {
type args struct {
tenantIDs []string
f func(string) time.Duration
}
tests := []struct {
name string
args args
want time.Duration
}{
{
name: "smallest positive non-zero duration per tenant",
args: args{
tenantIDs: []string{"tenant1", "tenantTwo", "tenantThree"},
f: func(tenantID string) time.Duration {
// For ease of testing just pick three unique values representing per-tenant limits
switch tenantID {
case "tenant1":
return time.Second
case "tenantTwo":
return 0
case "tenantThree":
return 2 * time.Second
default:
return 3 * time.Second
}
},
},
want: time.Second, // The smallest non-zero of the three
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := SmallestPositiveNonZeroDurationPerTenant(tt.args.tenantIDs, tt.args.f); got != tt.want {
t.Errorf("SmallestPositiveNonZeroDurationPerTenant() = %v, want %v", got, tt.want)
}
})
}
}
// nolint:goconst
func TestMaxDurationPerTenant(t *testing.T) {
type args struct {
tenantIDs []string
f func(string) time.Duration
}
tests := []struct {
name string
args args
want time.Duration
}{
{
name: "max duration per tenant",
args: args{
tenantIDs: []string{"tenant1", "tenantTwo", "tenantThree"},
f: func(tenantID string) time.Duration {
// For ease of testing just pick three unique values representing per-tenant limits
switch tenantID {
case "tenant1":
return time.Second
case "tenantTwo":
return 2 * time.Second
case "tenantThree":
return 3 * time.Second
default:
return time.Second
}
},
},
want: 3 * time.Second, // The largest of the three
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := MaxDurationPerTenant(tt.args.tenantIDs, tt.args.f); got != tt.want {
t.Errorf("MaxDurationPerTenant() = %v, want %v", got, tt.want)
}
})
}
}
// nolint:goconst
func TestMaxDurationOrZeroPerTenant(t *testing.T) {
type args struct {
tenantIDs []string
f func(string) time.Duration
}
tests := []struct {
name string
args args
want time.Duration
}{
{
name: "max duration or zero per tenant with no zero values",
args: args{
tenantIDs: []string{"tenant1", "tenantTwo", "tenantThree"},
f: func(tenantID string) time.Duration {
// For ease of testing just pick three unique values representing per-tenant limits
switch tenantID {
case "tenant1":
return time.Second
case "tenantTwo":
return 2 * time.Second
case "tenantThree":
return 3 * time.Second
default:
return time.Second
}
},
},
want: 3 * time.Second, // The largest of the three with no zero values present
},
{
name: "max duration or zero per tenant with zero values",
args: args{
tenantIDs: []string{"tenant1", "tenantTwo", "tenantThree"},
f: func(tenantID string) time.Duration {
// For ease of testing just pick three unique values representing per-tenant limits
switch tenantID {
case "tenant1":
return time.Second
case "tenantTwo":
return time.Duration(0)
case "tenantThree":
return 3 * time.Second
default:
return time.Second
}
},
},
want: time.Duration(0), // Return zero when a single tenant has a zero value
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := MaxDurationOrZeroPerTenant(tt.args.tenantIDs, tt.args.f); got != tt.want {
t.Errorf("MaxDurationOrZeroPerTenant() = %v, want %v", got, tt.want)
}
})
}
}
func TestIntersectionPerTenant(t *testing.T) {
tests := []struct {
name string
tenantIDs []string
f func(string) []string
expected []string
}{
{
name: "no tenants",
tenantIDs: []string{},
f: func(_ string) []string {
return nil
},
expected: []string{},
},
{
name: "single tenant with features",
tenantIDs: []string{"tenant1"},
f: func(tenantID string) []string {
if tenantID == "tenant1" {
return []string{"featureA", "featureB", "featureC"}
}
return nil
},
expected: []string{"featureA", "featureB", "featureC"},
},
{
name: "multiple tenants with common features",
tenantIDs: []string{"tenant1", "tenant2"},
f: func(tenantID string) []string {
if tenantID == "tenant1" {
return []string{"featureA", "featureB", "featureC"}
}
if tenantID == "tenant2" {
return []string{"featureB", "featureC", "featureD"}
}
return nil
},
expected: []string{"featureB", "featureC"},
},
{
name: "multiple tenants with no common features",
tenantIDs: []string{"tenant1", "tenant2"},
f: func(tenantID string) []string {
if tenantID == "tenant1" {
return []string{"featureA"}
}
if tenantID == "tenant2" {
return []string{"featureB"}
}
return nil
},
expected: []string{},
},
{
name: "multiple tenants with overlapping features",
tenantIDs: []string{"tenant1", "tenant2", "tenant3"},
f: func(tenantID string) []string {
if tenantID == "tenant1" {
return []string{"featureA", "featureB"}
}
if tenantID == "tenant2" {
return []string{"featureB", "featureC"}
}
if tenantID == "tenant3" {
return []string{"featureB", "featureD"}
}
return nil
},
expected: []string{"featureB"},
},
{
name: "tenant with empty feature set",
tenantIDs: []string{"tenant1", "tenant2"},
f: func(tenantID string) []string {
if tenantID == "tenant1" {
return []string{"featureA", "featureB"}
}
if tenantID == "tenant2" {
return []string{}
}
return nil
},
expected: []string{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
actual := IntersectionPerTenant(tt.tenantIDs, tt.f)
require.ElementsMatch(t, actual, tt.expected)
})
}
}