<commit_before>package google

import (
	"fmt"
	"regexp"
	"testing"
	"time"

	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
	"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

func TestProjectServiceServiceValidateFunc(t *testing.T) {
	cases := map[string]struct {
		val                   interface{}
		ExpectValidationError bool
	}{
		"ignoredProjectService": {
			val:                   "dataproc-control.googleapis.com",
			ExpectValidationError: true,
		},
		"bannedProjectService": {
			val:                   "bigquery-json.googleapis.com",
			ExpectValidationError: true,
		},
		"third party API": {
			val:                   "whatever.example.com",
			ExpectValidationError: false,
		},
		"not a domain": {
			val:                   "monitoring",
			ExpectValidationError: true,
		},
		"not a string": {
			val:                   5,
			ExpectValidationError: true,
		},
	}

	for tn, tc := range cases {
		_, errs := validateProjectServiceService(tc.val, "service")
		if tc.ExpectValidationError && len(errs) == 0 {
			t.Errorf("bad: %s, %q passed validation but was expected to fail", tn, tc.val)
		}
		if !tc.ExpectValidationError && len(errs) > 0 {
			t.Errorf("bad: %s, %q failed validation but was expected to pass. errs: %q", tn, tc.val, errs)
		}
	}
}

// Test that services can be enabled and disabled on a project
func TestAccProjectService_basic(t *testing.T) {
	t.Parallel()
	// Multiple fine-grained resources
	skipIfVcr(t)

	org := getTestOrgFromEnv(t)
	pid := fmt.Sprintf("tf-test-%d", randInt(t))
	services := []string{"iam.googleapis.com", "cloudresourcemanager.googleapis.com"}
	vcrTest(t, resource.TestCase{
		PreCheck:  func() { testAccPreCheck(t) },
		Providers: testAccProviders,
		Steps: []resource.TestStep{
			{
				Config: testAccProjectService_basic(services, pid, pname, org),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckProjectService(t, services, pid, true),
				),
			},
			{
				ResourceName:            "google_project_service.test",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"disable_on_destroy"},
			},
			{
				ResourceName:            "google_project_service.test2",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"disable_on_destroy", "project"},
			},
			// Use a separate TestStep rather than a CheckDestroy because we need the project to still exist.
			{
				Config: testAccProject_create(pid, pname, org),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckProjectService(t, services, pid, false),
				),
			},
			// Create services with disabling turned off.
			{
				Config: testAccProjectService_noDisable(services, pid, pname, org),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckProjectService(t, services, pid, true),
				),
			},
			// Check that services are still enabled even after the resources are deleted.
			{
				Config: testAccProject_create(pid, pname, org),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckProjectService(t, services, pid, true),
				),
			},
		},
	})
}

func TestAccProjectService_disableDependentServices(t *testing.T) {
	// Multiple fine-grained resources
	skipIfVcr(t)
	t.Parallel()

	org := getTestOrgFromEnv(t)
	billingId := getTestBillingAccountFromEnv(t)
	pid := fmt.Sprintf("tf-test-%d", randInt(t))
	services := []string{"cloudbuild.googleapis.com", "containerregistry.googleapis.com"}

	vcrTest(t, resource.TestCase{
		PreCheck:  func() { testAccPreCheck(t) },
		Providers: testAccProviders,
		Steps: []resource.TestStep{
			{
				Config: testAccProjectService_disableDependentServices(services, pid, pname, org, billingId, "false"),
			},
			{
				ResourceName:            "google_project_service.test",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"disable_on_destroy"},
			},
			{
				Config:      testAccProjectService_dependencyRemoved(services, pid, pname, org, billingId),
				ExpectError: regexp.MustCompile("Please specify disable_dependent_services=true if you want to proceed with disabling all services."),
			},
			{
				Config: testAccProjectService_disableDependentServices(services, pid, pname, org, billingId, "true"),
			},
			{
				ResourceName:            "google_project_service.test",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"disable_on_destroy"},
			},
			{
				Config:      testAccProjectService_dependencyRemoved(services, pid, pname, org, billingId),
				ExpectError: regexp.MustCompile("service .* not in enabled services for project"),
			},
		},<commit_msg>update expected error message for google project service disable dependent services test (#5466)<commit_after>package google

import (
	"fmt"
	"regexp"
	"testing"
	"time"

	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
	"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

func TestProjectServiceServiceValidateFunc(t *testing.T) {
	cases := map[string]struct {
		val                   interface{}
		ExpectValidationError bool
	}{
		"ignoredProjectService": {
			val:                   "dataproc-control.googleapis.com",
			ExpectValidationError: true,
		},
		"bannedProjectService": {
			val:                   "bigquery-json.googleapis.com",
			ExpectValidationError: true,
		},
		"third party API": {
			val:                   "whatever.example.com",
			ExpectValidationError: false,
		},
		"not a domain": {
			val:                   "monitoring",
			ExpectValidationError: true,
		},
		"not a string": {
			val:                   5,
			ExpectValidationError: true,
		},
	}

	for tn, tc := range cases {
		_, errs := validateProjectServiceService(tc.val, "service")
		if tc.ExpectValidationError && len(errs) == 0 {
			t.Errorf("bad: %s, %q passed validation but was expected to fail", tn, tc.val)
		}
		if !tc.ExpectValidationError && len(errs) > 0 {
			t.Errorf("bad: %s, %q failed validation but was expected to pass. errs: %q", tn, tc.val, errs)
		}
	}
}

// Test that services can be enabled and disabled on a project
func TestAccProjectService_basic(t *testing.T) {
	t.Parallel()
	// Multiple fine-grained resources
	skipIfVcr(t)

	org := getTestOrgFromEnv(t)
	pid := fmt.Sprintf("tf-test-%d", randInt(t))
	services := []string{"iam.googleapis.com", "cloudresourcemanager.googleapis.com"}
	vcrTest(t, resource.TestCase{
		PreCheck:  func() { testAccPreCheck(t) },
		Providers: testAccProviders,
		Steps: []resource.TestStep{
			{
				Config: testAccProjectService_basic(services, pid, pname, org),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckProjectService(t, services, pid, true),
				),
			},
			{
				ResourceName:            "google_project_service.test",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"disable_on_destroy"},
			},
			{
				ResourceName:            "google_project_service.test2",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"disable_on_destroy", "project"},
			},
			// Use a separate TestStep rather than a CheckDestroy because we need the project to still exist.
			{
				Config: testAccProject_create(pid, pname, org),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckProjectService(t, services, pid, false),
				),
			},
			// Create services with disabling turned off.
			{
				Config: testAccProjectService_noDisable(services, pid, pname, org),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckProjectService(t, services, pid, true),
				),
			},
			// Check that services are still enabled even after the resources are deleted.
			{
				Config: testAccProject_create(pid, pname, org),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckProjectService(t, services, pid, true),
				),
			},
		},
	})
}

func TestAccProjectService_disableDependentServices(t *testing.T) {
	// Multiple fine-grained resources
	skipIfVcr(t)
	t.Parallel()

	org := getTestOrgFromEnv(t)
	billingId := getTestBillingAccountFromEnv(t)
	pid := fmt.Sprintf("tf-test-%d", randInt(t))
	services := []string{"cloudbuild.googleapis.com", "containerregistry.googleapis.com"}

	vcrTest(t, resource.TestCase{
		PreCheck:  func() { testAccPreCheck(t) },
		Providers: testAccProviders,
		Steps: []resource.TestStep{
			{
				Config: testAccProjectService_disableDependentServices(services, pid, pname, org, billingId, "false"),
			},
			{
				ResourceName:            "google_project_service.test",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"disable_on_destroy"},
			},
			{
				Config:      testAccProjectService_dependencyRemoved(services, pid, pname, org, billingId),
				ExpectError: regexp.MustCompile("Please specify disable_dependent_services=true if you want to proceed with disabling all services."),
			},
			{
				Config: testAccProjectService_disableDependentServices(services, pid, pname, org, billingId, "true"),
			},
			{
				ResourceName:            "google_project_service.test",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"disable_on_destroy"},
			},
			{
				Config:             testAccProjectService_dependencyRemoved(services, pid, pname, org, billingId),
				ExpectNonEmptyPlan: true,
			},
		},
{'fraction_non_alphanumeric': 0.11742304030466519, 'fraction_numerical': 0.0016925843647519305, 'mean_word_length': 3.3910822108685554, 'pattern_counts': {'":': 10, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6616365', 'n_tokens_mistral': 3386, 'n_tokens_neox': 2908, 'n_words': 628}