// Copyright 2021 Google LLC
//
// 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 devicepolicy

import (
	"crypto/x509"
	"errors"
	"io/ioutil"
	"os"
	"path/filepath"
	"policy-manager/pkg/sysapi"
	pb "policy-manager/protos"
	"reflect"
	"testing"

	"github.com/golang/protobuf/proto"
)

var instanceConfig = &pb.InstanceConfig{
	MetricsEnabled: proto.Bool(true),
	UpdateStrategy: proto.String(""),
	HealthMonitorConfig: &pb.HealthMonitorConfig{
		Enforced:          proto.Bool(true),
		LoggingEnabled:    proto.Bool(true),
		MonitoringEnabled: proto.Bool(false),
	},
}

type fileManager struct {
	TmpDir                string
	TmpInstanceConfigFile string
	TmpDevicePolicyFile   string
	TmpPublicKeyFile      string
	TmpPrivateKeyFile     string
}

// generateFakePolicyBytes is a helper function to generate device policy bytes
// to simulate how device policy will be read from disk.
func generateFakePolicyBytes(t *testing.T, config *pb.InstanceConfig) (instanceConfigPolicyBytes []byte) {
	// Create fake policy.
	t.Helper()
	fakePolicy := new(DevicePolicy)
	fakePolicy.SetFromInstanceConfig(config)
	instanceConfigPolicyBytes, err := proto.Marshal(fakePolicy.instanceConfig)
	if err != nil {
		t.Fatal(err)
	}
	return instanceConfigPolicyBytes
}

// generateTmpFiles is a function to generate a tmp directory and names of
// device policy and key files.
func generateTmpFiles(t *testing.T) fileManager {
	var err error
	fileMgr := fileManager{}
	fileMgr.TmpDir, err = ioutil.TempDir("", "policy_manager_test_")
	if err != nil {
		t.Fatal(err)
	}

	fileMgr.TmpInstanceConfigFile = filepath.Join(fileMgr.TmpDir, "instance_config")
	fileMgr.TmpDevicePolicyFile = filepath.Join(fileMgr.TmpDir, "policy")
	fileMgr.TmpPublicKeyFile = filepath.Join(fileMgr.TmpDir, "owner.key")
	fileMgr.TmpPrivateKeyFile = filepath.Join(fileMgr.TmpDir, "private.key")

	return fileMgr
}

// TestCreateKeyFiles tests that the function is writing to the keys to the
// correct files with the right permissions.
func TestCreateKeyFiles(t *testing.T) {
	// Generate tmp policy file and key names
	fileMgr := generateTmpFiles(t)
	createKeyFiles(fileMgr.TmpPublicKeyFile, fileMgr.TmpPrivateKeyFile)
	defer os.RemoveAll(fileMgr.TmpDir)

	// Check if the file exists
	if _, err := os.Stat(fileMgr.TmpPublicKeyFile); errors.Is(err, os.ErrNotExist) {
		t.Error("Public key file not created")
	}

	if _, err := os.Stat(fileMgr.TmpPrivateKeyFile); errors.Is(err, os.ErrNotExist) {
		t.Error("Private key file not created")
	}
}

// TestCheckKeyFiles tests that the checkKeyFiles function checks for the
// existence of both the private and public key files as well as whether the
// public and private keys match.
func TestCheckKeyFiles(t *testing.T) {
	// Generate tmp policy file and key names
	fileMgr := generateTmpFiles(t)
	// Generate another tmp policy file and key names
	newFileMgr := generateTmpFiles(t)

	createKeyFiles(fileMgr.TmpPublicKeyFile, fileMgr.TmpPrivateKeyFile)
	createKeyFiles(newFileMgr.TmpPublicKeyFile, newFileMgr.TmpPrivateKeyFile)

	defer os.RemoveAll(fileMgr.TmpDir)
	defer os.RemoveAll(newFileMgr.TmpDir)

	tests := []struct {
		name           string
		publicKeyFile  string
		privateKeyFile string
		expectErr      bool
	}{
		{
			"Good Key Pair",
			fileMgr.TmpPublicKeyFile,
			fileMgr.TmpPrivateKeyFile,
			false,
		},
		{
			"Non-matching Key Pair",
			fileMgr.TmpPublicKeyFile,
			newFileMgr.TmpPrivateKeyFile,
			true,
		},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			privateKeyBytes, err := ioutil.ReadFile(test.privateKeyFile)
			if err != nil {
				t.Fatalf("error reading key file: %v", err)
			}

			privateKey, err := x509.ParsePKCS1PrivateKey(privateKeyBytes)
			if err != nil {
				t.Fatalf("error generating private key: %v", err)
			}

			privateKeyResult, err := checkKeyFiles(test.publicKeyFile, test.privateKeyFile)

			if err == nil {
				if test.expectErr {
					t.Errorf("test %s passed, expect error",
						test.name)
				} else if !reflect.DeepEqual(privateKeyResult, privateKey) {
					t.Errorf("test %s got private key %v, expect %v",
						test.name, privateKeyResult, privateKey)
				}
			} else {
				if !test.expectErr {
					t.Errorf("test %s got error %v, expect to pass",
						test.name, err)
				}
			}
		})
	}
}

// TestInitDevicePolicyNoOnDiskPolicy tests the scenario where InitDevicePolicy() is called
// with a nil InstanceConfig when one of device policy file missing.
func TestInitDevicePolicyNoOnDiskPolicy(t *testing.T) {
	// Generate tmp policy file and key names
	fileMgr := generateTmpFiles(t)

	expectedInstanceConfig := GetDefaultInstanceConfigFromBase(&pb.InstanceConfig{})
	expectedInstanceConfigBytes := generateFakePolicyBytes(t, expectedInstanceConfig)

	// Expect the policy files to be written.
	sysapi.AtomicWriteFile(fileMgr.TmpInstanceConfigFile, expectedInstanceConfigBytes, configFilePerm)
	defer os.RemoveAll(fileMgr.TmpDir)

	if err := InitDevicePolicy(nil, fileMgr.TmpDevicePolicyFile, fileMgr.TmpInstanceConfigFile, fileMgr.TmpPublicKeyFile, fileMgr.TmpPrivateKeyFile); err != nil {
		t.Error(err)
	}
	if generatedConfig, err := GetInstanceConfig(fileMgr.TmpInstanceConfigFile); err != nil {
		t.Error(err)
	} else {
		if !proto.Equal(generatedConfig, expectedInstanceConfig) {
			t.Errorf("got %s, expected %s",
				proto.MarshalTextString(generatedConfig),
				proto.MarshalTextString(expectedInstanceConfig))
		}
	}

}

// TestInitDevicePolicyValidPolicy tests the scenario where InitDevicePolicy() is called
// with a valid InstanceConfig when a device policy files already exist. In this case,
// the files are re-written.
func TestInitDevicePolicyValidPolicy(t *testing.T) {
	// Create fake policy.
	instanceConfigPolicyBytes := generateFakePolicyBytes(t, instanceConfig)

	// Generate tmp policy file and key names
	fileMgr := generateTmpFiles(t)

	// Initialization process should not create default policy files if the
	// existing policy files are valid.
	sysapi.AtomicWriteFile(fileMgr.TmpInstanceConfigFile, instanceConfigPolicyBytes, configFilePerm)
	defer os.RemoveAll(fileMgr.TmpDir)

	newInstanceConfig := GetDefaultInstanceConfigFromBase(&pb.InstanceConfig{})
	newInstanceConfigPolicyBytes := generateFakePolicyBytes(t, newInstanceConfig)

	// Expect the policy files to be written.
	sysapi.AtomicWriteFile(fileMgr.TmpInstanceConfigFile, newInstanceConfigPolicyBytes, configFilePerm)

	if err := InitDevicePolicy(&pb.InstanceConfig{}, fileMgr.TmpDevicePolicyFile, fileMgr.TmpInstanceConfigFile, fileMgr.TmpPublicKeyFile, fileMgr.TmpPrivateKeyFile); err != nil {
		t.Error(err)
	}
	if generatedConfig, err := GetInstanceConfig(fileMgr.TmpInstanceConfigFile); err != nil {
		t.Error(err)
	} else {
		if !proto.Equal(generatedConfig, newInstanceConfig) {
			t.Errorf("got %s, expected %s",
				proto.MarshalTextString(generatedConfig),
				proto.MarshalTextString(newInstanceConfig))
		}
	}
}

// TestInitDevicePolicyWithBasePolicy tests the InitDevicePolicy() function when a custom
// base policy is specified.
func TestInitDevicePolicyWithBasePolicy(t *testing.T) {
	// Create fake policy.
	instanceConfigPolicyBytes := generateFakePolicyBytes(t, instanceConfig)

	// Generate tmp policy file and key names
	fileMgr := generateTmpFiles(t)

	sysapi.AtomicWriteFile(fileMgr.TmpInstanceConfigFile, instanceConfigPolicyBytes, configFilePerm)
	defer os.RemoveAll(fileMgr.TmpDir)

	// Use custom base policy.
	newInstanceConfig := GetDefaultInstanceConfigFromBase(
		&pb.InstanceConfig{
			UpdateStrategy: proto.String(""),
		})
	newInstanceConfigPolicyBytes := generateFakePolicyBytes(t, newInstanceConfig)

	// Expect the policy to be written.
	sysapi.AtomicWriteFile(fileMgr.TmpInstanceConfigFile, newInstanceConfigPolicyBytes, configFilePerm)

	if err := InitDevicePolicy(newInstanceConfig, fileMgr.TmpDevicePolicyFile, fileMgr.TmpInstanceConfigFile, fileMgr.TmpPublicKeyFile, fileMgr.TmpPrivateKeyFile); err != nil {
		t.Error(err)
	}
	if generatedConfig, err := GetInstanceConfig(fileMgr.TmpInstanceConfigFile); err != nil {
		t.Error(err)
	} else {
		if !proto.Equal(generatedConfig, newInstanceConfig) {
			t.Errorf("got %s, expected %s",
				proto.MarshalTextString(generatedConfig),
				proto.MarshalTextString(newInstanceConfig))
		}
	}
}

// TestInitDevicePolicyWithoutBasePolicy tests that when baseConfig is nil but
// there are existing device policy on disk, the existing device policy should
// be populated with missing default fields and re-written to disk if changed.
func TestInitDevicePolicyWithNilBasePolicy(t *testing.T) {
	// Create mock on-disk device policy.
	currentConfig := &pb.InstanceConfig{
		MetricsEnabled: proto.Bool(false),
		UpdateStrategy: proto.String(""),
	}
	currentConfig = GetDefaultInstanceConfigFromBase(currentConfig)
	currentinstanceConfigPolicyBytes := generateFakePolicyBytes(t, currentConfig)

	// Generate tmp policy file and key names
	fileMgr := generateTmpFiles(t)

	// Make sure the initialization process ensures that the policy
	// directory is present.
	sysapi.AtomicWriteFile(fileMgr.TmpInstanceConfigFile, currentinstanceConfigPolicyBytes, configFilePerm)
	defer os.RemoveAll(fileMgr.TmpDir)

	if err := InitDevicePolicy(nil, fileMgr.TmpDevicePolicyFile, fileMgr.TmpInstanceConfigFile, fileMgr.TmpPublicKeyFile, fileMgr.TmpPrivateKeyFile); err != nil {
		t.Error(err)
	}
	if generatedConfig, err := GetInstanceConfig(fileMgr.TmpInstanceConfigFile); err != nil {
		t.Error(err)
	} else {
		if !proto.Equal(generatedConfig, currentConfig) {
			t.Errorf("got %s, expected %s",
				proto.MarshalTextString(generatedConfig),
				proto.MarshalTextString(currentConfig))
		}
	}
}

// TestSetInstanceConfig_NewConfig tests whether the SetInstanceConfig function is able to
// correctly write new device policy files to disk.
func TestSetInstanceConfig_NewConfig(t *testing.T) {
	// Create fake policy.
	instanceConfigPolicyBytes := generateFakePolicyBytes(t, instanceConfig)

	// Generate tmp policy file and key names
	fileMgr := generateTmpFiles(t)

	// Policy file doesn't exist, so a new file should be created.
	sysapi.AtomicWriteFile(fileMgr.TmpInstanceConfigFile, instanceConfigPolicyBytes, configFilePerm)
	defer os.RemoveAll(fileMgr.TmpDir)

	if err := InitDevicePolicy(nil, fileMgr.TmpDevicePolicyFile, fileMgr.TmpInstanceConfigFile, fileMgr.TmpPublicKeyFile, fileMgr.TmpPrivateKeyFile); err != nil {
		t.Error(err)
	}
	if err := SetInstanceConfig(instanceConfig, fileMgr.TmpDevicePolicyFile, fileMgr.TmpInstanceConfigFile, fileMgr.TmpPublicKeyFile, fileMgr.TmpPrivateKeyFile); err != nil {
		t.Error(err)
	}
	if generatedConfig, err := GetInstanceConfig(fileMgr.TmpInstanceConfigFile); err != nil {
		t.Error(err)
	} else {
		if !proto.Equal(generatedConfig, instanceConfig) {
			t.Errorf("got %s, expected %s",
				proto.MarshalTextString(generatedConfig),
				proto.MarshalTextString(instanceConfig))
		}
	}
}

// TestSetInstanceConfig_UpdatedConfig tests whether the SetInstanceConfig function is able to
// correctly update the existing device policy file on disk.
func TestSetInstanceConfig_UpdatedConfig(t *testing.T) {

	// Create fake policy.
	instanceConfigPolicyBytes := generateFakePolicyBytes(t, instanceConfig)

	// Generate tmp policy file and key names
	fileMgr := generateTmpFiles(t)

	// Policy files exist.
	sysapi.AtomicWriteFile(fileMgr.TmpInstanceConfigFile, instanceConfigPolicyBytes, configFilePerm)
	defer os.RemoveAll(fileMgr.TmpDir)

	// This is different than original instanceConfig.
	newInstanceConfig := GetDefaultInstanceConfigFromBase(
		&pb.InstanceConfig{
			UpdateStrategy: proto.String(""),
			HealthMonitorConfig: &pb.HealthMonitorConfig{
				Enforced:       proto.Bool(true),
				LoggingEnabled: proto.Bool(false),
			},
		})
	newInstanceConfigPolicyBytes := generateFakePolicyBytes(t, newInstanceConfig)

	sysapi.AtomicWriteFile(fileMgr.TmpInstanceConfigFile, newInstanceConfigPolicyBytes, configFilePerm)

	if err := InitDevicePolicy(nil, fileMgr.TmpDevicePolicyFile, fileMgr.TmpInstanceConfigFile, fileMgr.TmpPublicKeyFile, fileMgr.TmpPrivateKeyFile); err != nil {
		t.Error(err)
	}

	if err := SetInstanceConfig(newInstanceConfig, fileMgr.TmpDevicePolicyFile, fileMgr.TmpInstanceConfigFile, fileMgr.TmpPublicKeyFile, fileMgr.TmpPrivateKeyFile); err != nil {
		t.Error(err)
	}
	if generatedConfig, err := GetInstanceConfig(fileMgr.TmpInstanceConfigFile); err != nil {
		t.Error(err)
	} else {
		if !proto.Equal(generatedConfig, newInstanceConfig) {
			t.Errorf("got %s, expected %s",
				proto.MarshalTextString(generatedConfig),
				proto.MarshalTextString(newInstanceConfig))
		}
	}
}

// TestSetInstanceConfig_IdenticalConfig tests whether the SetInstanceConfig function skips
// writing the policy files when there is no change in the instance config.
func TestSetInstanceConfig_IdenticalConfig(t *testing.T) {
	// Create fake policy.
	instanceConfigPolicyBytes := generateFakePolicyBytes(t, instanceConfig)

	// Generate tmp policy file and key names
	fileMgr := generateTmpFiles(t)

	// Policy files exist.
	sysapi.AtomicWriteFile(fileMgr.TmpInstanceConfigFile, instanceConfigPolicyBytes, configFilePerm)
	defer os.RemoveAll(fileMgr.TmpDir)

	// AtomicWriteFile not expected since there is no change in the instanceConfig.
	if err := InitDevicePolicy(nil, fileMgr.TmpDevicePolicyFile, fileMgr.TmpInstanceConfigFile, fileMgr.TmpPublicKeyFile, fileMgr.TmpPrivateKeyFile); err != nil {
		t.Error(err)
	}

	if err := SetInstanceConfig(instanceConfig, fileMgr.TmpDevicePolicyFile, fileMgr.TmpInstanceConfigFile, fileMgr.TmpPublicKeyFile, fileMgr.TmpPrivateKeyFile); err != nil {
		t.Error(err)
	}
	if generatedConfig, err := GetInstanceConfig(fileMgr.TmpInstanceConfigFile); err != nil {
		t.Error(err)
	} else {
		if !proto.Equal(generatedConfig, instanceConfig) {
			t.Errorf("got %s, expected %s",
				proto.MarshalTextString(generatedConfig),
				proto.MarshalTextString(instanceConfig))
		}
	}
}

// TestSetInstanceConfig_EmptyConfig tests whether the SetInstanceConfig function sets
// correct default values when an empty InstanceConfig is passed.
func TestSetInstanceConfig_EmptyConfig(t *testing.T) {

	// Create fake policy. Start with default instnace config.
	defaultInstanceConfig := GetDefaultInstanceConfigFromBase(&pb.InstanceConfig{})
	instanceConfigPolicyBytes := generateFakePolicyBytes(t, defaultInstanceConfig)

	// Generate tmp policy file and key names
	fileMgr := generateTmpFiles(t)

	sysapi.AtomicWriteFile(fileMgr.TmpInstanceConfigFile, instanceConfigPolicyBytes, configFilePerm)
	defer os.RemoveAll(fileMgr.TmpDir)

	// This is just an empty instnace config.
	emptyInstanceConfig := &pb.InstanceConfig{}

	if err := InitDevicePolicy(nil, fileMgr.TmpDevicePolicyFile, fileMgr.TmpInstanceConfigFile, fileMgr.TmpPublicKeyFile, fileMgr.TmpPrivateKeyFile); err != nil {
		t.Error(err)
	}

	if err := SetInstanceConfig(emptyInstanceConfig, fileMgr.TmpDevicePolicyFile, fileMgr.TmpInstanceConfigFile, fileMgr.TmpPublicKeyFile, fileMgr.TmpPrivateKeyFile); err != nil {
		t.Error(err)
	}
	if generatedConfig, err := GetInstanceConfig(fileMgr.TmpInstanceConfigFile); err != nil {
		t.Error(err)
	} else {
		if !proto.Equal(generatedConfig, defaultInstanceConfig) {
			t.Errorf("got %s, expected %s",
				proto.MarshalTextString(generatedConfig),
				proto.MarshalTextString(defaultInstanceConfig))
		}
	}
}

// TestSetInstanceConfig_NilConfig tests whether the SetInstanceConfig function sets
// correct default values when an nil InstnaceConfig is passed.
func TestSetInstanceConfig_NilConfig(t *testing.T) {

	// Create fake policy. Start with default instnace config.
	defaultInstanceConfig := GetDefaultInstanceConfigFromBase(&pb.InstanceConfig{})
	instanceConfigPolicyBytes := generateFakePolicyBytes(t, defaultInstanceConfig)

	// Generate tmp policy file and key names
	fileMgr := generateTmpFiles(t)

	sysapi.AtomicWriteFile(fileMgr.TmpInstanceConfigFile, instanceConfigPolicyBytes, configFilePerm)
	defer os.RemoveAll(fileMgr.TmpDir)

	if err := InitDevicePolicy(nil, fileMgr.TmpDevicePolicyFile, fileMgr.TmpInstanceConfigFile, fileMgr.TmpPublicKeyFile, fileMgr.TmpPrivateKeyFile); err != nil {
		t.Error(err)
	}

	if err := SetInstanceConfig(nil, fileMgr.TmpDevicePolicyFile, fileMgr.TmpInstanceConfigFile, fileMgr.TmpPublicKeyFile, fileMgr.TmpPrivateKeyFile); err != nil {
		t.Error(err)
	}
	if generatedConfig, err := GetInstanceConfig(fileMgr.TmpInstanceConfigFile); err != nil {
		t.Error(err)
	} else {
		if !proto.Equal(generatedConfig, defaultInstanceConfig) {
			t.Errorf("got %s, expected %s",
				proto.MarshalTextString(generatedConfig),
				proto.MarshalTextString(defaultInstanceConfig))
		}
	}
}

// TestSetInstanceConfig_RemoveConfig tests whether the SetInstanceConfig function sets
// correct default values for a removed config option.
func TestSetInstanceConfig_RemoveConfig(t *testing.T) {

	// Create fake policy.
	instanceConfigPolicyBytes := generateFakePolicyBytes(t, instanceConfig)

	// Generate tmp policy file and key names
	fileMgr := generateTmpFiles(t)

	// Policy file exist; simulate its read.
	sysapi.AtomicWriteFile(fileMgr.TmpInstanceConfigFile, instanceConfigPolicyBytes, configFilePerm)
	defer os.RemoveAll(fileMgr.TmpDir)

	// Note that MetricsEnabled is not specified.
	newInstanceConfig := &pb.InstanceConfig{
		UpdateStrategy: proto.String(""),
		HealthMonitorConfig: &pb.HealthMonitorConfig{
			Enforced:       proto.Bool(true),
			LoggingEnabled: proto.Bool(true),
		},
	}

	// expectedInstanceConfig is same as newInstanceConfig with default value for the
	// missing config option.
	expectedInstanceConfig := &pb.InstanceConfig{
		MetricsEnabled: proto.Bool(false),
		UpdateStrategy: proto.String(""),
		HealthMonitorConfig: &pb.HealthMonitorConfig{
			Enforced:          proto.Bool(true),
			LoggingEnabled:    proto.Bool(true),
			MonitoringEnabled: proto.Bool(false),
		},
	}
	expectedInstanceConfigBytes := generateFakePolicyBytes(t, expectedInstanceConfig)

	sysapi.AtomicWriteFile(fileMgr.TmpInstanceConfigFile, expectedInstanceConfigBytes, configFilePerm)
	defer os.RemoveAll(fileMgr.TmpInstanceConfigFile)
	defer os.RemoveAll(fileMgr.TmpPublicKeyFile)
	defer os.RemoveAll(fileMgr.TmpPrivateKeyFile)
	defer os.RemoveAll(fileMgr.TmpDevicePolicyFile)

	if err := InitDevicePolicy(nil, fileMgr.TmpDevicePolicyFile, fileMgr.TmpInstanceConfigFile, fileMgr.TmpPublicKeyFile, fileMgr.TmpPrivateKeyFile); err != nil {
		t.Error(err)
	}

	if err := SetInstanceConfig(newInstanceConfig, fileMgr.TmpDevicePolicyFile, fileMgr.TmpInstanceConfigFile, fileMgr.TmpPublicKeyFile, fileMgr.TmpPrivateKeyFile); err != nil {
		t.Error(err)
	}

	if generatedConfig, err := GetInstanceConfig(fileMgr.TmpInstanceConfigFile); err != nil {
		t.Error(err)
	} else {
		if !proto.Equal(generatedConfig, expectedInstanceConfig) {
			t.Errorf("got %s, expected %s",
				proto.MarshalTextString(generatedConfig),
				proto.MarshalTextString(expectedInstanceConfig))
		}
	}
}

// TestGetDefaultInstanceConfigFromBase tests that we always generate the expect default
// update config.
func TestGetDefaultInstanceConfigFromBase(t *testing.T) {
	// Expected default config.
	config := &pb.InstanceConfig{
		MetricsEnabled: proto.Bool(false),
		UpdateStrategy: proto.String(""),
		HealthMonitorConfig: &pb.HealthMonitorConfig{
			Enforced:          proto.Bool(false),
			LoggingEnabled:    proto.Bool(false),
			MonitoringEnabled: proto.Bool(false),
		},
	}

	tests := []struct {
		name           string
		baseConfig     *pb.InstanceConfig
		expectedConfig *pb.InstanceConfig
	}{
		{
			"NilBaseConfig",
			nil,
			config,
		},
		{
			"EmptyBaseConfig",
			&pb.InstanceConfig{
				HealthMonitorConfig: &pb.HealthMonitorConfig{},
			},
			config,
		},
		{
			"BaseConfigWithMetricsEnabled",
			&pb.InstanceConfig{
				MetricsEnabled: proto.Bool(true),
			},
			&pb.InstanceConfig{
				MetricsEnabled: proto.Bool(true),
				UpdateStrategy: proto.String(""),
				HealthMonitorConfig: &pb.HealthMonitorConfig{
					Enforced:          proto.Bool(false),
					LoggingEnabled:    proto.Bool(false),
					MonitoringEnabled: proto.Bool(false),
				},
			},
		},
		{
			"BaseConfigWithUpdateStrategy",
			&pb.InstanceConfig{
				UpdateStrategy: proto.String(""),
			},
			&pb.InstanceConfig{
				MetricsEnabled: proto.Bool(false),
				UpdateStrategy: proto.String(""),
				HealthMonitorConfig: &pb.HealthMonitorConfig{
					Enforced:          proto.Bool(false),
					LoggingEnabled:    proto.Bool(false),
					MonitoringEnabled: proto.Bool(false),
				},
			},
		},
		{
			"BaseConfigWithMultipleFields",
			&pb.InstanceConfig{
				MetricsEnabled: proto.Bool(true),
				UpdateStrategy: proto.String(""),
			},
			&pb.InstanceConfig{
				MetricsEnabled: proto.Bool(true),
				UpdateStrategy: proto.String(""),
				HealthMonitorConfig: &pb.HealthMonitorConfig{
					Enforced:          proto.Bool(false),
					LoggingEnabled:    proto.Bool(false),
					MonitoringEnabled: proto.Bool(false),
				},
			},
		},
		{
			"BaseConfigEnablingLoggingMissingMonitoring",
			&pb.InstanceConfig{
				UpdateStrategy: proto.String(""),
				HealthMonitorConfig: &pb.HealthMonitorConfig{
					Enforced:       proto.Bool(true),
					LoggingEnabled: proto.Bool(true),
				},
			},
			&pb.InstanceConfig{
				MetricsEnabled: proto.Bool(false),
				UpdateStrategy: proto.String(""),
				HealthMonitorConfig: &pb.HealthMonitorConfig{
					Enforced:          proto.Bool(true),
					LoggingEnabled:    proto.Bool(true),
					MonitoringEnabled: proto.Bool(false),
				},
			},
		},
		{
			"BaseConfigEnforcedNotEnableLoggingMonitoring",
			&pb.InstanceConfig{
				HealthMonitorConfig: &pb.HealthMonitorConfig{
					Enforced:          proto.Bool(true),
					LoggingEnabled:    proto.Bool(false),
					MonitoringEnabled: proto.Bool(false),
				},
			},
			&pb.InstanceConfig{
				MetricsEnabled: proto.Bool(false),
				UpdateStrategy: proto.String(""),
				HealthMonitorConfig: &pb.HealthMonitorConfig{
					Enforced:          proto.Bool(true),
					LoggingEnabled:    proto.Bool(false),
					MonitoringEnabled: proto.Bool(false),
				},
			},
		},
		{
			"BaseConfigEnableLoggingAndMonitoring",
			&pb.InstanceConfig{
				HealthMonitorConfig: &pb.HealthMonitorConfig{
					Enforced:          proto.Bool(true),
					LoggingEnabled:    proto.Bool(true),
					MonitoringEnabled: proto.Bool(true),
				},
			},
			&pb.InstanceConfig{
				MetricsEnabled: proto.Bool(false),
				UpdateStrategy: proto.String(""),
				HealthMonitorConfig: &pb.HealthMonitorConfig{
					Enforced:          proto.Bool(true),
					LoggingEnabled:    proto.Bool(true),
					MonitoringEnabled: proto.Bool(true),
				},
			},
		},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			generatedConfig := GetDefaultInstanceConfigFromBase(test.baseConfig)
			if !proto.Equal(generatedConfig, test.expectedConfig) {
				t.Errorf("got %s, expected %s",
					proto.MarshalTextString(generatedConfig),
					proto.MarshalTextString(test.expectedConfig))
			}
		})
	}
}
