/*
 *
 * 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 (
	"testing"

	"google.golang.org/grpc/internal/grpctest"
)

type s struct {
	grpctest.Tester
}

func Test(t *testing.T) {
	grpctest.RunSubTests(t, s{})
}

// Test that get method logger returns the one with the most exact match.
func (s) TestGetMethodLogger(t *testing.T) {
	testCases := []struct {
		in       string
		method   string
		hdr, msg uint64
	}{
		// Global.
		{
			in:     "*{h:12;m:23}",
			method: "/s/m",
			hdr:    12, msg: 23,
		},
		// service/*.
		{
			in:     "*,s/*{h:12;m:23}",
			method: "/s/m",
			hdr:    12, msg: 23,
		},
		// Service/method.
		{
			in:     "*{h;m},s/m{h:12;m:23}",
			method: "/s/m",
			hdr:    12, msg: 23,
		},
		{
			in:     "*{h;m},s/*{h:314;m},s/m{h:12;m:23}",
			method: "/s/m",
			hdr:    12, msg: 23,
		},
		{
			in:     "*{h;m},s/*{h:12;m:23},s/m",
			method: "/s/m",
			hdr:    maxUInt, msg: maxUInt,
		},

		// service/*.
		{
			in:     "*{h;m},s/*{h:12;m:23},s/m1",
			method: "/s/m",
			hdr:    12, msg: 23,
		},
		{
			in:     "*{h;m},s1/*,s/m{h:12;m:23}",
			method: "/s/m",
			hdr:    12, msg: 23,
		},

		// With black list.
		{
			in:     "*{h:12;m:23},-s/m1",
			method: "/s/m",
			hdr:    12, msg: 23,
		},
	}
	for _, tc := range testCases {
		l := NewLoggerFromConfigString(tc.in)
		if l == nil {
			t.Errorf("in: %q, failed to create logger from config string", tc.in)
			continue
		}
		ml := l.GetMethodLogger(tc.method).(*TruncatingMethodLogger)
		if ml == nil {
			t.Errorf("in: %q, method logger is nil, want non-nil", tc.in)
			continue
		}
		if ml.headerMaxLen != tc.hdr || ml.messageMaxLen != tc.msg {
			t.Errorf("in: %q, want header: %v, message: %v, got header: %v, message: %v", tc.in, tc.hdr, tc.msg, ml.headerMaxLen, ml.messageMaxLen)
		}
	}
}

// expect method logger to be nil
func (s) TestGetMethodLoggerOff(t *testing.T) {
	testCases := []struct {
		in     string
		method string
	}{
		// method not specified.
		{
			in:     "s1/m",
			method: "/s/m",
		},
		{
			in:     "s/m1",
			method: "/s/m",
		},
		{
			in:     "s1/*",
			method: "/s/m",
		},
		{
			in:     "s1/*,s/m1",
			method: "/s/m",
		},

		// blacklisted.
		{
			in:     "*,-s/m",
			method: "/s/m",
		},
		{
			in:     "s/*,-s/m",
			method: "/s/m",
		},
		{
			in:     "-s/m,s/*",
			method: "/s/m",
		},
	}
	for _, tc := range testCases {
		l := NewLoggerFromConfigString(tc.in)
		if l == nil {
			t.Errorf("in: %q, failed to create logger from config string", tc.in)
			continue
		}
		ml := l.GetMethodLogger(tc.method)
		if ml != nil {
			t.Errorf("in: %q, method logger is non-nil, want nil", tc.in)
		}
	}
}
