// Copyright 2015 Google Inc. All rights reserved.
//
// 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 proptools

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

var clonePropertiesTestCases = []struct {
	in  interface{}
	out interface{}
	err error
}{
	// Valid inputs

	{
		// Clone bool
		in: &struct{ B1, B2 bool }{
			B1: true,
			B2: false,
		},
		out: &struct{ B1, B2 bool }{
			B1: true,
			B2: false,
		},
	},
	{
		// Clone strings
		in: &struct{ S string }{
			S: "string1",
		},
		out: &struct{ S string }{
			S: "string1",
		},
	},
	{
		// Clone slice
		in: &struct{ S []string }{
			S: []string{"string1"},
		},
		out: &struct{ S []string }{
			S: []string{"string1"},
		},
	},
	{
		// Clone empty slice
		in: &struct{ S []string }{
			S: []string{},
		},
		out: &struct{ S []string }{
			S: []string{},
		},
	},
	{
		// Clone nil slice
		in:  &struct{ S []string }{},
		out: &struct{ S []string }{},
	},
	{
		// Clone pointer to bool
		in: &struct{ B1, B2 *bool }{
			B1: BoolPtr(true),
			B2: BoolPtr(false),
		},
		out: &struct{ B1, B2 *bool }{
			B1: BoolPtr(true),
			B2: BoolPtr(false),
		},
	},
	{
		// Clone pointer to string
		in: &struct{ S *string }{
			S: StringPtr("string1"),
		},
		out: &struct{ S *string }{
			S: StringPtr("string1"),
		},
	},
	{
		// Clone struct
		in: &struct{ S struct{ S string } }{
			S: struct{ S string }{
				S: "string1",
			},
		},
		out: &struct{ S struct{ S string } }{
			S: struct{ S string }{
				S: "string1",
			},
		},
	},
	{
		// Clone struct pointer
		in: &struct{ S *struct{ S string } }{
			S: &struct{ S string }{
				S: "string1",
			},
		},
		out: &struct{ S *struct{ S string } }{
			S: &struct{ S string }{
				S: "string1",
			},
		},
	},
	{
		// Clone interface
		in: &struct{ S interface{} }{
			S: &struct{ S string }{
				S: "string1",
			},
		},
		out: &struct{ S interface{} }{
			S: &struct{ S string }{
				S: "string1",
			},
		},
	},
	{
		// Empty struct
		in:  &struct{}{},
		out: &struct{}{},
	},
	{
		// Interface nil
		in: &struct{ S interface{} }{
			S: nil,
		},
		out: &struct{ S interface{} }{
			S: nil,
		},
	},
	{
		// Interface pointer to nil
		in: &struct{ S interface{} }{
			S: (*struct{ S string })(nil),
		},
		out: &struct{ S interface{} }{
			S: (*struct{ S string })(nil),
		},
	},
	{
		// Pointer nil
		in: &struct{ S *struct{} }{
			S: nil,
		},
		out: &struct{ S *struct{} }{
			S: nil,
		},
	},
}

func TestCloneProperties(t *testing.T) {
	for _, testCase := range clonePropertiesTestCases {
		testString := fmt.Sprintf("%s", testCase.in)

		got := CloneProperties(reflect.ValueOf(testCase.in).Elem()).Interface()

		if !reflect.DeepEqual(testCase.out, got) {
			t.Errorf("test case %s", testString)
			t.Errorf("incorrect output")
			t.Errorf("  expected: %#v", testCase.out)
			t.Errorf("       got: %#v", got)
		}
	}
}

var cloneEmptyPropertiesTestCases = []struct {
	in  interface{}
	out interface{}
	err error
}{
	// Valid inputs

	{
		// Clone bool
		in: &struct{ B1, B2 bool }{
			B1: true,
			B2: false,
		},
		out: &struct{ B1, B2 bool }{},
	},
	{
		// Clone strings
		in: &struct{ S string }{
			S: "string1",
		},
		out: &struct{ S string }{},
	},
	{
		// Clone slice
		in: &struct{ S []string }{
			S: []string{"string1"},
		},
		out: &struct{ S []string }{},
	},
	{
		// Clone empty slice
		in: &struct{ S []string }{
			S: []string{},
		},
		out: &struct{ S []string }{},
	},
	{
		// Clone nil slice
		in:  &struct{ S []string }{},
		out: &struct{ S []string }{},
	},
	{
		// Clone pointer to bool
		in: &struct{ B1, B2 *bool }{
			B1: BoolPtr(true),
			B2: BoolPtr(false),
		},
		out: &struct{ B1, B2 *bool }{},
	},
	{
		// Clone pointer to string
		in: &struct{ S *string }{
			S: StringPtr("string1"),
		},
		out: &struct{ S *string }{},
	},
	{
		// Clone struct
		in: &struct{ S struct{ S string } }{
			S: struct{ S string }{
				S: "string1",
			},
		},
		out: &struct{ S struct{ S string } }{
			S: struct{ S string }{},
		},
	},
	{
		// Clone struct pointer
		in: &struct{ S *struct{ S string } }{
			S: &struct{ S string }{
				S: "string1",
			},
		},
		out: &struct{ S *struct{ S string } }{
			S: &struct{ S string }{},
		},
	},
	{
		// Clone interface
		in: &struct{ S interface{} }{
			S: &struct{ S string }{
				S: "string1",
			},
		},
		out: &struct{ S interface{} }{
			S: &struct{ S string }{},
		},
	},
	{
		// Empty struct
		in:  &struct{}{},
		out: &struct{}{},
	},
	{
		// Interface nil
		in: &struct{ S interface{} }{
			S: nil,
		},
		out: &struct{ S interface{} }{},
	},
	{
		// Interface pointer to nil
		in: &struct{ S interface{} }{
			S: (*struct{ S string })(nil),
		},
		out: &struct{ S interface{} }{
			S: (*struct{ S string })(nil),
		},
	},
	{
		// Pointer nil
		in: &struct{ S *struct{} }{
			S: nil,
		},
		out: &struct{ S *struct{} }{},
	},
}

func TestCloneEmptyProperties(t *testing.T) {
	for _, testCase := range cloneEmptyPropertiesTestCases {
		testString := fmt.Sprintf("%s", testCase.in)

		got := CloneEmptyProperties(reflect.ValueOf(testCase.in).Elem()).Interface()

		if !reflect.DeepEqual(testCase.out, got) {
			t.Errorf("test case %s", testString)
			t.Errorf("incorrect output")
			t.Errorf("  expected: %#v", testCase.out)
			t.Errorf("       got: %#v", got)
		}
	}
}

func TestZeroProperties(t *testing.T) {
	for _, testCase := range cloneEmptyPropertiesTestCases {
		testString := fmt.Sprintf("%s", testCase.in)

		got := CloneEmptyProperties(reflect.ValueOf(testCase.in).Elem()).Interface()
		ZeroProperties(reflect.ValueOf(got).Elem())

		if !reflect.DeepEqual(testCase.out, got) {
			t.Errorf("test case %s", testString)
			t.Errorf("incorrect output")
			t.Errorf("  expected: %#v", testCase.out)
			t.Errorf("       got: %#v", got)
		}
	}
}
