/*
 *
 * Copyright 2014 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 transport

import (
	"fmt"
	"reflect"
	"testing"
	"time"
)

func TestTimeoutEncode(t *testing.T) {
	for _, test := range []struct {
		in  string
		out string
	}{
		{"12345678ns", "12345678n"},
		{"123456789ns", "123457u"},
		{"12345678us", "12345678u"},
		{"123456789us", "123457m"},
		{"12345678ms", "12345678m"},
		{"123456789ms", "123457S"},
		{"12345678s", "12345678S"},
		{"123456789s", "2057614M"},
		{"12345678m", "12345678M"},
		{"123456789m", "2057614H"},
	} {
		d, err := time.ParseDuration(test.in)
		if err != nil {
			t.Fatalf("failed to parse duration string %s: %v", test.in, err)
		}
		out := encodeTimeout(d)
		if out != test.out {
			t.Fatalf("timeoutEncode(%s) = %s, want %s", test.in, out, test.out)
		}
	}
}

func TestTimeoutDecode(t *testing.T) {
	for _, test := range []struct {
		// input
		s string
		// output
		d   time.Duration
		err error
	}{
		{"1234S", time.Second * 1234, nil},
		{"1234x", 0, fmt.Errorf("transport: timeout unit is not recognized: %q", "1234x")},
		{"1", 0, fmt.Errorf("transport: timeout string is too short: %q", "1")},
		{"", 0, fmt.Errorf("transport: timeout string is too short: %q", "")},
	} {
		d, err := decodeTimeout(test.s)
		if d != test.d || fmt.Sprint(err) != fmt.Sprint(test.err) {
			t.Fatalf("timeoutDecode(%q) = %d, %v, want %d, %v", test.s, int64(d), err, int64(test.d), test.err)
		}
	}
}

func TestContentSubtype(t *testing.T) {
	tests := []struct {
		contentType string
		want        string
		wantValid   bool
	}{
		{"application/grpc", "", true},
		{"application/grpc+", "", true},
		{"application/grpc+blah", "blah", true},
		{"application/grpc;", "", true},
		{"application/grpc;blah", "blah", true},
		{"application/grpcd", "", false},
		{"application/grpd", "", false},
		{"application/grp", "", false},
	}
	for _, tt := range tests {
		got, gotValid := contentSubtype(tt.contentType)
		if got != tt.want || gotValid != tt.wantValid {
			t.Errorf("contentSubtype(%q) = (%v, %v); want (%v, %v)", tt.contentType, got, gotValid, tt.want, tt.wantValid)
		}
	}
}

func TestEncodeGrpcMessage(t *testing.T) {
	for _, tt := range []struct {
		input    string
		expected string
	}{
		{"", ""},
		{"Hello", "Hello"},
		{"my favorite character is \u0000", "my favorite character is %00"},
		{"my favorite character is %", "my favorite character is %25"},
	} {
		actual := encodeGrpcMessage(tt.input)
		if tt.expected != actual {
			t.Errorf("encodeGrpcMessage(%v) = %v, want %v", tt.input, actual, tt.expected)
		}
	}
}

func TestDecodeGrpcMessage(t *testing.T) {
	for _, tt := range []struct {
		input    string
		expected string
	}{
		{"", ""},
		{"Hello", "Hello"},
		{"H%61o", "Hao"},
		{"H%6", "H%6"},
		{"%G0", "%G0"},
		{"%E7%B3%BB%E7%BB%9F", "系统"},
	} {
		actual := decodeGrpcMessage(tt.input)
		if tt.expected != actual {
			t.Errorf("dncodeGrpcMessage(%v) = %v, want %v", tt.input, actual, tt.expected)
		}
	}
}

const binaryValue = string(128)

func TestEncodeMetadataHeader(t *testing.T) {
	for _, test := range []struct {
		// input
		kin string
		vin string
		// output
		vout string
	}{
		{"key", "abc", "abc"},
		{"KEY", "abc", "abc"},
		{"key-bin", "abc", "YWJj"},
		{"key-bin", binaryValue, "woA"},
	} {
		v := encodeMetadataHeader(test.kin, test.vin)
		if !reflect.DeepEqual(v, test.vout) {
			t.Fatalf("encodeMetadataHeader(%q, %q) = %q, want %q", test.kin, test.vin, v, test.vout)
		}
	}
}

func TestDecodeMetadataHeader(t *testing.T) {
	for _, test := range []struct {
		// input
		kin string
		vin string
		// output
		vout string
		err  error
	}{
		{"a", "abc", "abc", nil},
		{"key-bin", "Zm9vAGJhcg==", "foo\x00bar", nil},
		{"key-bin", "Zm9vAGJhcg", "foo\x00bar", nil},
		{"key-bin", "woA=", binaryValue, nil},
		{"a", "abc,efg", "abc,efg", nil},
	} {
		v, err := decodeMetadataHeader(test.kin, test.vin)
		if !reflect.DeepEqual(v, test.vout) || !reflect.DeepEqual(err, test.err) {
			t.Fatalf("decodeMetadataHeader(%q, %q) = %q, %v, want %q, %v", test.kin, test.vin, v, err, test.vout, test.err)
		}
	}
}
