// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/otlp/observ/target_test.go.tmpl

// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package {{ .pkg }}

import "testing"

func TestParseTarget(t *testing.T) {
	// gRPC target naming is defined here:
	// https://github.com/grpc/grpc/blob/74232c6bd3c0f4bc35bad035dbeecf5cbc834a11/doc/naming.md
	//
	// The Go gRPC client only supports the "dns", "unix", "unix-abstract", and
	// "passthrough" schemes natively with "dns" being the default:
	// https://pkg.go.dev/google.golang.org/grpc@v1.75.1/internal/resolver
	//
	// Other schemes (e.g., "consul", "zk") are supported via custom resolvers
	// that can be registered with the gRPC resolver package. These custom
	// resolvers are still expected to follow the general target string format
	// when rendered with the CanonicalTarget method:
	//
	//   <scheme>://<authority>/<endpoint>
	//
	// All target strings in these tests are rendered with the
	// CanonicalTarget method. Therefore they all follow the above format.
	tests := []struct {
		target string
		host   string
		port   int
	}{
		// DNS scheme: hostname and port.
		{target: "dns:///:8080", host: "", port: 8080},
		{target: "dns:///example.com", host: "example.com", port: -1},
		{target: "dns:///example.com%eth0", host: "example.com%eth0", port: -1},
		{target: "dns:///example.com:42", host: "example.com", port: 42},
		{target: "dns:///example.com%eth0:42", host: "example.com%eth0", port: 42},

		// DNS scheme: hostname and port with authority.
		{target: "dns://8.8.8.8/example.com", host: "example.com", port: -1},
		{target: "dns://8.8.8.8/example.com%eth0", host: "example.com%eth0", port: -1},
		{target: "dns://8.8.8.8/example.com:42", host: "example.com", port: 42},
		{target: "dns://8.8.8.8/example.com%eth0:42", host: "example.com%eth0", port: 42},

		// DNS scheme: IPv4 address and port.
		{target: "dns:///192.168.1.1", host: "192.168.1.1", port: -1},
		{target: "dns:///192.168.1.1%eth0", host: "192.168.1.1%eth0", port: -1},
		{target: "dns:///192.168.1.1:8080", host: "192.168.1.1", port: 8080},
		{target: "dns:///192.168.1.1%eth0:8080", host: "192.168.1.1%eth0", port: 8080},

		// DNS scheme: IPv6 address and port.
		{target: "dns:///2001:0db8:85a3:0000:0000:8a2e:0370:7334", host: "2001:db8:85a3::8a2e:370:7334", port: -1},
		{target: "dns:///2001:db8:85a3:0:0:8a2e:370:7334", host: "2001:db8:85a3::8a2e:370:7334", port: -1},
		{target: "dns:///2001:db8:85a3::8a2e:370:7334", host: "2001:db8:85a3::8a2e:370:7334", port: -1},
		{target: "dns:///2001:db8:85a3::8a2e:370:7334%eth0", host: "2001:db8:85a3::8a2e:370:7334%eth0", port: -1},
		{target: "dns:///[2001:db8:85a3::8a2e:370:7334]", host: "2001:db8:85a3::8a2e:370:7334", port: -1},
		{target: "dns:///[2001:db8:85a3::8a2e:370:7334%eth0]", host: "2001:db8:85a3::8a2e:370:7334%eth0", port: -1},
		{target: "dns:///[::1]:9090", host: "::1", port: 9090},
		{target: "dns:///[::1%eth0]:9090", host: "::1%eth0", port: 9090},

		// Unix domain sockets.
		{target: "unix:///tmp/grpc.sock", host: "/tmp/grpc.sock", port: -1},
		{target: "unix:///absolute_path", host: "/absolute_path", port: -1},

		// Unix domain socket in abstract namespace.
		{target: "unix-abstract:///abstract-socket-name", host: "/abstract-socket-name", port: -1},

		// International domain names.
		{target: "dns:///测试.example.com:8080", host: "测试.example.com", port: 8080},

		// Port edge cases.
		{target: "dns:///example.com:0", host: "example.com", port: 0},
		{target: "dns:///example.com:65535", host: "example.com", port: 65535},

		// Case sensitivity.
		{target: "dns:///EXAMPLE.COM:8080", host: "EXAMPLE.COM", port: 8080},
		{target: "dns:///Example.Com:8080", host: "Example.Com", port: 8080},

		// Custom and passthrough resolvers scheme
		{target: "passthrough:///localhost:50051", host: "localhost", port: 50051},
		{target: "passthrough:///10.0.0.2:7777", host: "10.0.0.2", port: 7777},
		{target: "consul:///my-service", host: "my-service", port: -1},
		{target: "zk:///services/my-service", host: "services/my-service", port: -1},
	}

	for _, tt := range tests {
		host, port, err := ParseCanonicalTarget(tt.target)
		if err != nil {
			t.Errorf("parseTarget(%q) unexpected error: %v", tt.target, err)
			continue
		}
		if host != tt.host {
			t.Errorf("parseTarget(%q) host = %q, want %q", tt.target, host, tt.host)
		}
		if port != tt.port {
			t.Errorf("parseTarget(%q) port = %d, want %d", tt.target, port, tt.port)
		}
	}
}

func TestParseTargetErrors(t *testing.T) {
	targets := []string{
		"dns:///example.com:invalid",     // Non-numeric port in URL.
		"dns:///example.com:8080:9090",   // Multiple colons in port.
		"dns:///example.com:99999",       // Port out of range.
		"dns:///example.com:-1",          // Port out of range.
		"unix://localhost/sock",          // Non-empty authority for unix scheme.
		"unix:",                          // Empty unix scheme.
		"unix-abstract://",               // Empty unix-abstract scheme.
		"unix-abstract://authority/sock", // Non-empty authority for unix-abstract scheme.
		"contains-cont\roll-cha\rs",      // Invalid URL.
	}

	for _, target := range targets {
		host, port, err := ParseCanonicalTarget(target)
		if err == nil {
			t.Errorf("parseTarget(%q) expected error, got nil", target)
		}

		if host != "" {
			t.Errorf("parseTarget(%q) host = %q, want empty", target, host)
		}

		if port != -1 {
			t.Errorf("parseTarget(%q) port = %d, want -1", target, port)
		}
	}
}

func BenchmarkParseTarget(b *testing.B) {
	benchmarks := []struct {
		name   string
		target string
	}{
		{"HostName", "dns:///example.com"},
		{"HostPort", "dns:///example.com:8080"},
		{"IPv4WithoutPort", "dns:///192.168.1.1"},
		{"IPv4WithPort", "dns:///192.168.1.1:8080"},
		{"IPv6Bare", "dns:///2001:db8::1"},
		{"IPv6Bracket", "dns:///[2001:db8::1]"},
		{"IPv6WithPort", "dns:///[2001:db8::1]:8080"},
		{"UnixSocket", "unix:///tmp/grpc.sock"},
		{"UnixAbstractSocket", "unix-abstract:///abstract-socket-name"},
		{"Passthrough", "passthrough:///localhost:50051"},
	}

	var (
		host string
		port int
		err  error
	)
	for _, bm := range benchmarks {
		b.Run(bm.name, func(b *testing.B) {
			b.ReportAllocs()
			for b.Loop() {
				host, port, err = ParseCanonicalTarget(bm.target)
			}
		})
	}
	_, _, _ = host, port, err
}
