/*
 * Copyright 2022 CloudWeGo 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 metadata

import (
	"testing"

	"golang.org/x/net/context"

	"github.com/cloudwego/kitex/internal/test"
)

func TestDecodeKeyValue(t *testing.T) {
	key1, value1 := "k1", "v1"
	k, v, err := DecodeKeyValue(key1, value1)
	test.Assert(t, k == key1)
	test.Assert(t, v == value1)
	test.Assert(t, err == nil, err)
}

func TestPairs(t *testing.T) {
	key1, value1 := "k1", "v1"
	// new pairs
	md := Pairs(key1, value1)

	v1 := md.Get(key1)[0]
	test.Assert(t, v1 == value1)
}

func TestMetadata(t *testing.T) {
	key1, key2, key3 := "k1", "k2", "k3"
	value1, value2, value3 := "v1", "v2", "v3"
	value11 := "v11"
	value2m := "v2m"
	m := map[string]string{}
	m[key1] = value1
	m[key2] = value2
	m[key3] = value3
	md := New(m)

	// test Len()
	test.Assert(t, md.Len() == len(m))
	// test Get()
	test.Assert(t, md.Get(key1)[0] == value1)
	// test Append()
	md.Append(key1)
	test.Assert(t, len(md.Get(key1)) == 1)
	md.Append(key1, value11)
	test.Assert(t, md.Get(key1)[1] == value11)
	// test Set()
	md.Set(key2)
	test.Assert(t, md.Get(key2)[0] == value2)
	md.Set(key2, value2m)
	test.Assert(t, md.Get(key2)[0] == value2m)
	// test Copy()
	copiedMd := md.Copy()
	test.Assert(t, copiedMd.Get(key3)[0] == value3)
}

func TestContext(t *testing.T) {
	key1, value1 := "k1", "v1"
	md := Pairs(key1, value1)

	// test incomingCtx
	incomingCtx := NewIncomingContext(context.Background(), md)
	_, incomingOk := FromIncomingContext(incomingCtx)
	test.Assert(t, incomingOk)

	// test outgoingCtx
	outgoingCtx := NewOutgoingContext(context.Background(), md)
	_, outgoingOk := FromOutgoingContext(outgoingCtx)
	test.Assert(t, outgoingOk)

	key2, key3, value2, value3 := "k2", "k3", "v2", "v3"
	// test outgoingCtxRaw
	AppendToOutgoingContext(outgoingCtx, key2, value2, key3, value3)
	_, _, outgoingRawOk := FromOutgoingContextRaw(outgoingCtx)
	test.Assert(t, outgoingRawOk)
}

func TestAppendMD(t *testing.T) {
	t.Run("empty-md", func(t *testing.T) {
		md := AppendMD(nil, MD{"k1": {"v1"}})
		test.Assert(t, md.Get("k1")[0] == "v1")
	})
	t.Run("empty-other", func(t *testing.T) {
		md := AppendMD(MD{"k1": {"v1"}}, nil)
		test.Assert(t, md.Get("k1")[0] == "v1")
	})
	t.Run("no-same-key", func(t *testing.T) {
		md := AppendMD(MD{"k1": {"v1"}, "k3": {"v3"}}, MD{"k2": {"v2"}})
		test.Assert(t, md.Get("k1")[0] == "v1")
		test.Assert(t, md.Get("k2")[0] == "v2")
		test.Assert(t, md.Get("k3")[0] == "v3")
	})
	t.Run("same-key", func(t *testing.T) {
		md := AppendMD(MD{"k1": {"v1"}}, MD{"k1": {"v2"}, "k2": {"v3"}})
		test.Assert(t, md.Get("k1")[0] == "v1")
		test.Assert(t, md.Get("k1")[1] == "v2")
		test.Assert(t, md.Get("k2")[0] == "v3")
	})
}
