blob: aced5d5585d819ef1d84ac21d12ec6f5b23dd031 [file] [log] [blame]
/*
*
* Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package binarylog
import (
"fmt"
"testing"
)
// This tests that when multiple configs are specified, all methods loggers will
// be set correctly. Correctness of each logger is covered by other unit tests.
func TestNewLoggerFromConfigString(t *testing.T) {
const (
s1 = "s1"
m1 = "m1"
m2 = "m2"
fullM1 = s1 + "/" + m1
fullM2 = s1 + "/" + m2
)
c := fmt.Sprintf("*{h:1;m:2},%s{h},%s{m},%s{h;m}", s1+"/*", fullM1, fullM2)
l := NewLoggerFromConfigString(c).(*logger)
if l.all.hdr != 1 || l.all.msg != 2 {
t.Errorf("l.all = %#v, want headerLen: 1, messageLen: 2", l.all)
}
if ml, ok := l.services[s1]; ok {
if ml.hdr != maxUInt || ml.msg != 0 {
t.Errorf("want maxUInt header, 0 message, got header: %v, message: %v", ml.hdr, ml.msg)
}
} else {
t.Errorf("service/* is not set")
}
if ml, ok := l.methods[fullM1]; ok {
if ml.hdr != 0 || ml.msg != maxUInt {
t.Errorf("want 0 header, maxUInt message, got header: %v, message: %v", ml.hdr, ml.msg)
}
} else {
t.Errorf("service/method{h} is not set")
}
if ml, ok := l.methods[fullM2]; ok {
if ml.hdr != maxUInt || ml.msg != maxUInt {
t.Errorf("want maxUInt header, maxUInt message, got header: %v, message: %v", ml.hdr, ml.msg)
}
} else {
t.Errorf("service/method{h;m} is not set")
}
}
func TestNewLoggerFromConfigStringInvalid(t *testing.T) {
testCases := []string{
"",
"*{}",
"s/m,*{}",
"s/m,s/m{a}",
// Duplciate rules.
"s/m,-s/m",
"-s/m,s/m",
"s/m,s/m",
"s/m,s/m{h:1;m:1}",
"s/m{h:1;m:1},s/m",
"-s/m,-s/m",
"s/*,s/*{h:1;m:1}",
"*,*{h:1;m:1}",
}
for _, tc := range testCases {
l := NewLoggerFromConfigString(tc)
if l != nil {
t.Errorf("With config %q, want logger %v, got %v", tc, nil, l)
}
}
}
func TestParseMethodConfigAndSuffix(t *testing.T) {
testCases := []struct {
in, service, method, suffix string
}{
{
in: "p.s/m",
service: "p.s", method: "m", suffix: "",
},
{
in: "p.s/m{h,m}",
service: "p.s", method: "m", suffix: "{h,m}",
},
{
in: "p.s/*",
service: "p.s", method: "*", suffix: "",
},
{
in: "p.s/*{h,m}",
service: "p.s", method: "*", suffix: "{h,m}",
},
// invalid suffix will be detected by another function.
{
in: "p.s/m{invalidsuffix}",
service: "p.s", method: "m", suffix: "{invalidsuffix}",
},
{
in: "p.s/*{invalidsuffix}",
service: "p.s", method: "*", suffix: "{invalidsuffix}",
},
{
in: "s/m*",
service: "s", method: "m", suffix: "*",
},
{
in: "s/*m",
service: "s", method: "*", suffix: "m",
},
{
in: "s/**",
service: "s", method: "*", suffix: "*",
},
}
for _, tc := range testCases {
t.Logf("testing parseMethodConfigAndSuffix(%q)", tc.in)
s, m, suffix, err := parseMethodConfigAndSuffix(tc.in)
if err != nil {
t.Errorf("returned error %v, want nil", err)
continue
}
if s != tc.service {
t.Errorf("service = %q, want %q", s, tc.service)
}
if m != tc.method {
t.Errorf("method = %q, want %q", m, tc.method)
}
if suffix != tc.suffix {
t.Errorf("suffix = %q, want %q", suffix, tc.suffix)
}
}
}
func TestParseMethodConfigAndSuffixInvalid(t *testing.T) {
testCases := []string{
"*/m",
"*/m{}",
}
for _, tc := range testCases {
s, m, suffix, err := parseMethodConfigAndSuffix(tc)
if err == nil {
t.Errorf("Parsing %q got nil error with %q, %q, %q, want non-nil error", tc, s, m, suffix)
}
}
}
func TestParseHeaderMessageLengthConfig(t *testing.T) {
testCases := []struct {
in string
hdr, msg uint64
}{
{
in: "",
hdr: maxUInt, msg: maxUInt,
},
{
in: "{h}",
hdr: maxUInt, msg: 0,
},
{
in: "{h:314}",
hdr: 314, msg: 0,
},
{
in: "{m}",
hdr: 0, msg: maxUInt,
},
{
in: "{m:213}",
hdr: 0, msg: 213,
},
{
in: "{h;m}",
hdr: maxUInt, msg: maxUInt,
},
{
in: "{h:314;m}",
hdr: 314, msg: maxUInt,
},
{
in: "{h;m:213}",
hdr: maxUInt, msg: 213,
},
{
in: "{h:314;m:213}",
hdr: 314, msg: 213,
},
}
for _, tc := range testCases {
t.Logf("testing parseHeaderMessageLengthConfig(%q)", tc.in)
hdr, msg, err := parseHeaderMessageLengthConfig(tc.in)
if err != nil {
t.Errorf("returned error %v, want nil", err)
continue
}
if hdr != tc.hdr {
t.Errorf("header length = %v, want %v", hdr, tc.hdr)
}
if msg != tc.msg {
t.Errorf("message length = %v, want %v", msg, tc.msg)
}
}
}
func TestParseHeaderMessageLengthConfigInvalid(t *testing.T) {
testCases := []string{
"{}",
"{h;a}",
"{h;m;b}",
}
for _, tc := range testCases {
_, _, err := parseHeaderMessageLengthConfig(tc)
if err == nil {
t.Errorf("Parsing %q got nil error, want non-nil error", tc)
}
}
}
func TestFillMethodLoggerWithConfigStringBlacklist(t *testing.T) {
testCases := []string{
"p.s/m",
"service/method",
}
for _, tc := range testCases {
c := "-" + tc
t.Logf("testing fillMethodLoggerWithConfigString(%q)", c)
l := newEmptyLogger()
if err := l.fillMethodLoggerWithConfigString(c); err != nil {
t.Errorf("returned err %v, want nil", err)
continue
}
_, ok := l.blacklist[tc]
if !ok {
t.Errorf("blacklist[%q] is not set", tc)
}
}
}
func TestFillMethodLoggerWithConfigStringGlobal(t *testing.T) {
testCases := []struct {
in string
hdr, msg uint64
}{
{
in: "",
hdr: maxUInt, msg: maxUInt,
},
{
in: "{h}",
hdr: maxUInt, msg: 0,
},
{
in: "{h:314}",
hdr: 314, msg: 0,
},
{
in: "{m}",
hdr: 0, msg: maxUInt,
},
{
in: "{m:213}",
hdr: 0, msg: 213,
},
{
in: "{h;m}",
hdr: maxUInt, msg: maxUInt,
},
{
in: "{h:314;m}",
hdr: 314, msg: maxUInt,
},
{
in: "{h;m:213}",
hdr: maxUInt, msg: 213,
},
{
in: "{h:314;m:213}",
hdr: 314, msg: 213,
},
}
for _, tc := range testCases {
c := "*" + tc.in
t.Logf("testing fillMethodLoggerWithConfigString(%q)", c)
l := newEmptyLogger()
if err := l.fillMethodLoggerWithConfigString(c); err != nil {
t.Errorf("returned err %v, want nil", err)
continue
}
if l.all == nil {
t.Errorf("l.all is not set")
continue
}
if hdr := l.all.hdr; hdr != tc.hdr {
t.Errorf("header length = %v, want %v", hdr, tc.hdr)
}
if msg := l.all.msg; msg != tc.msg {
t.Errorf("message length = %v, want %v", msg, tc.msg)
}
}
}
func TestFillMethodLoggerWithConfigStringPerService(t *testing.T) {
testCases := []struct {
in string
hdr, msg uint64
}{
{
in: "",
hdr: maxUInt, msg: maxUInt,
},
{
in: "{h}",
hdr: maxUInt, msg: 0,
},
{
in: "{h:314}",
hdr: 314, msg: 0,
},
{
in: "{m}",
hdr: 0, msg: maxUInt,
},
{
in: "{m:213}",
hdr: 0, msg: 213,
},
{
in: "{h;m}",
hdr: maxUInt, msg: maxUInt,
},
{
in: "{h:314;m}",
hdr: 314, msg: maxUInt,
},
{
in: "{h;m:213}",
hdr: maxUInt, msg: 213,
},
{
in: "{h:314;m:213}",
hdr: 314, msg: 213,
},
}
const serviceName = "service"
for _, tc := range testCases {
c := serviceName + "/*" + tc.in
t.Logf("testing fillMethodLoggerWithConfigString(%q)", c)
l := newEmptyLogger()
if err := l.fillMethodLoggerWithConfigString(c); err != nil {
t.Errorf("returned err %v, want nil", err)
continue
}
ml, ok := l.services[serviceName]
if !ok {
t.Errorf("l.service[%q] is not set", serviceName)
continue
}
if hdr := ml.hdr; hdr != tc.hdr {
t.Errorf("header length = %v, want %v", hdr, tc.hdr)
}
if msg := ml.msg; msg != tc.msg {
t.Errorf("message length = %v, want %v", msg, tc.msg)
}
}
}
func TestFillMethodLoggerWithConfigStringPerMethod(t *testing.T) {
testCases := []struct {
in string
hdr, msg uint64
}{
{
in: "",
hdr: maxUInt, msg: maxUInt,
},
{
in: "{h}",
hdr: maxUInt, msg: 0,
},
{
in: "{h:314}",
hdr: 314, msg: 0,
},
{
in: "{m}",
hdr: 0, msg: maxUInt,
},
{
in: "{m:213}",
hdr: 0, msg: 213,
},
{
in: "{h;m}",
hdr: maxUInt, msg: maxUInt,
},
{
in: "{h:314;m}",
hdr: 314, msg: maxUInt,
},
{
in: "{h;m:213}",
hdr: maxUInt, msg: 213,
},
{
in: "{h:314;m:213}",
hdr: 314, msg: 213,
},
}
const (
serviceName = "service"
methodName = "method"
fullMethodName = serviceName + "/" + methodName
)
for _, tc := range testCases {
c := fullMethodName + tc.in
t.Logf("testing fillMethodLoggerWithConfigString(%q)", c)
l := newEmptyLogger()
if err := l.fillMethodLoggerWithConfigString(c); err != nil {
t.Errorf("returned err %v, want nil", err)
continue
}
ml, ok := l.methods[fullMethodName]
if !ok {
t.Errorf("l.methods[%q] is not set", fullMethodName)
continue
}
if hdr := ml.hdr; hdr != tc.hdr {
t.Errorf("header length = %v, want %v", hdr, tc.hdr)
}
if msg := ml.msg; msg != tc.msg {
t.Errorf("message length = %v, want %v", msg, tc.msg)
}
}
}
func TestFillMethodLoggerWithConfigStringInvalid(t *testing.T) {
testCases := []string{
"",
"{}",
"p.s/m{}",
"p.s/m{a}",
"p.s/m*",
"p.s/**",
"*/m",
"-p.s/*",
"-p.s/m{h}",
}
l := &logger{}
for _, tc := range testCases {
if err := l.fillMethodLoggerWithConfigString(tc); err == nil {
t.Errorf("fillMethodLoggerWithConfigString(%q) returned nil error, want non-nil", tc)
}
}
}