Ctrl K
ComunidadGuías…

pkg/envs/envs_test.go

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package envs_test

import (
	"testing"

	"github.com/shellhub-io/shellhub/pkg/envs"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestParseEdition(t *testing.T) {
	t.Parallel()

	tests := []struct {
		description string
		raw         string
		expected    envs.Edition
		expectErr   bool
	}{
		{description: "empty is community", raw: "", expected: envs.Community},
		{description: "explicit community", raw: "community", expected: envs.Community},
		{description: "explicit enterprise", raw: "enterprise", expected: envs.Enterprise},
		{description: "explicit cloud", raw: "cloud", expected: envs.Cloud},
		{description: "uppercase is normalized", raw: "CLOUD", expected: envs.Cloud},
		{description: "mixed case is normalized", raw: "Enterprise", expected: envs.Enterprise},
		{description: "whitespace is trimmed", raw: "  cloud  ", expected: envs.Cloud},
		{description: "unknown value is an error", raw: "invalid", expectErr: true},
	}

	for _, tt := range tests {
		t.Run(tt.description, func(t *testing.T) {
			t.Parallel()

			edition, err := envs.ParseEdition(tt.raw)
			if tt.expectErr {
				require.Error(t, err)

				return
			}

			require.NoError(t, err)
			assert.Equal(t, tt.expected, edition)
		})
	}
}

func TestEditionPredicates(t *testing.T) {
	t.Parallel()

	tests := []struct {
		description         string
		edition             envs.Edition
		isCommunity         bool
		isEnterprise        bool
		isCloud             bool
		isEnterpriseOrCloud bool
	}{
		{"zero value", "", true, false, false, false},
		{"community", envs.Community, true, false, false, false},
		{"enterprise", envs.Enterprise, false, true, false, true},
		{"cloud", envs.Cloud, false, false, true, true},
	}

	for _, tt := range tests {
		t.Run(tt.description, func(t *testing.T) {
			t.Parallel()

			assert.Equal(t, tt.isCommunity, tt.edition.IsCommunity())
			assert.Equal(t, tt.isEnterprise, tt.edition.IsEnterprise())
			assert.Equal(t, tt.isCloud, tt.edition.IsCloud())
			assert.Equal(t, tt.isEnterpriseOrCloud, tt.edition.IsEnterpriseOrCloud())
		})
	}
}

func TestParse_edition(t *testing.T) {
	t.Parallel()

	type Envs struct {
		Edition envs.Edition `env:"SHELLHUB_EDITION"`
	}

	t.Run("unset is the zero value", func(t *testing.T) {
		t.Parallel()

		result, err := envs.Parse[Envs](envs.Map(nil))
		require.NoError(t, err)
		assert.True(t, result.Edition.IsCommunity())
	})

	t.Run("a valid value is normalized", func(t *testing.T) {
		t.Parallel()

		result, err := envs.Parse[Envs](envs.Map(map[string]string{"SHELLHUB_EDITION": " Cloud "}))
		require.NoError(t, err)
		assert.Equal(t, envs.Cloud, result.Edition)
	})

	t.Run("an invalid value fails the parse", func(t *testing.T) {
		t.Parallel()

		_, err := envs.Parse[Envs](envs.Map(map[string]string{"SHELLHUB_EDITION": "invalid"}))
		assert.ErrorIs(t, err, envs.ErrParse)
	})
}

func TestParseWithPrefix_with_default(t *testing.T) {
	t.Parallel()

	type Envs struct {
		RedisURI string `env:"REDIS_URI,default=redis://redis:6379/default"`
		MongoURI string `env:"MONGO_URI,default=mongodb://mongo:27017/default"`
	}

	type Expected struct {
		Envs  *Envs
		Error error
	}

	tests := []struct {
		description string
		prefix      string
		values      map[string]string
		expected    Expected
	}{
		{
			description: "parse envs with prefix empty",
			prefix:      "",
			values: map[string]string{
				"REDIS_URI": "redis://redis:6379/empty",
				"MONGO_URI": "mongodb://mongo:27017/empty",
			},
			expected: Expected{
				Envs: &Envs{
					RedisURI: "redis://redis:6379/empty",
					MongoURI: "mongodb://mongo:27017/empty",
				},
				Error: nil,
			},
		},
		{
			description: "parse envs with one prefix and an empty",
			prefix:      "FOO_",
			values: map[string]string{
				"FOO_REDIS_URI": "redis://redis:6379/foo",
				"REDIS_URI":     "redis://redis:6379/empty",
				"MONGO_URI":     "mongodb://mongo:27017/empty",
			},
			expected: Expected{
				Envs: &Envs{
					RedisURI: "redis://redis:6379/foo",
					MongoURI: "mongodb://mongo:27017/empty",
				},
				Error: nil,
			},
		},
		{
			description: "parse envs with one prefix",
			prefix:      "BAR_",
			values: map[string]string{
				"FOO_REDIS_URI": "redis://redis:6379/foo",
				"BAR_REDIS_URI": "redis://redis:6379/bar",
				"FOO_MONGO_URI": "mongodb://mongo:27017/foo",
				"BAR_MONGO_URI": "mongodb://mongo:27017/bar",
			},
			expected: Expected{
				Envs: &Envs{
					RedisURI: "redis://redis:6379/bar",
					MongoURI: "mongodb://mongo:27017/bar",
				},
				Error: nil,
			},
		},
		{
			description: "parse envs with one prefix and default",
			prefix:      "FOO_",
			values: map[string]string{
				"FOO_REDIS_URI": "redis://redis:6379/foo",
				"BAR_REDIS_URI": "redis://redis:6379/bar",
				"BAR_MONGO_URI": "mongodb://mongo:27017/bar",
			},
			expected: Expected{
				Envs: &Envs{
					RedisURI: "redis://redis:6379/foo",
					MongoURI: "mongodb://mongo:27017/default",
				},
				Error: nil,
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.description, func(t *testing.T) {
			t.Parallel()

			result, err := envs.ParseWithPrefix[Envs](envs.Map(tt.values), tt.prefix)
			assert.Equal(t, tt.expected.Envs, result)
			assert.ErrorIs(t, err, tt.expected.Error)
		})
	}
}

func TestParseWithPrefix_with_required(t *testing.T) {
	t.Parallel()

	type Envs struct {
		RedisURI string `env:"REDIS_URI,required"`
		MongoURI string `env:"MONGO_URI,required"`
	}

	type Expected struct {
		Envs  *Envs
		Error error
	}

	tests := []struct {
		description string
		prefix      string
		values      map[string]string
		expected    Expected
	}{
		{
			description: "parse envs with a prefix and no prefixed",
			prefix:      "FOO_",
			values: map[string]string{
				"FOO_REDIS_URI": "redis://redis:6379/foo",
				"MONGO_URI":     "mongodb://mongo:27017/empty",
			},
			expected: Expected{
				Envs: &Envs{
					RedisURI: "redis://redis:6379/foo",
					MongoURI: "mongodb://mongo:27017/empty",
				},
				Error: nil,
			},
		},
		{
			description: "parse envs with a prefix and only unprefixed",
			prefix:      "FOO_",
			values: map[string]string{
				"REDIS_URI": "redis://redis:6379/empty",
				"MONGO_URI": "mongodb://mongo:27017/empty",
			},
			expected: Expected{
				Envs: &Envs{
					RedisURI: "redis://redis:6379/empty",
					MongoURI: "mongodb://mongo:27017/empty",
				},
				Error: nil,
			},
		},
		{
			description: "fails to parse when two different prefixes",
			prefix:      "FOO_",
			values: map[string]string{
				"FOO_REDIS_URI": "redis://redis:6379/foo",
				"BAR_MONGO_URI": "mongodb://mongo:27017/empty",
			},
			expected: Expected{
				Envs:  nil,
				Error: envs.ErrParseWithPrefix,
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.description, func(t *testing.T) {
			t.Parallel()

			result, err := envs.ParseWithPrefix[Envs](envs.Map(tt.values), tt.prefix)
			assert.Equal(t, tt.expected.Envs, result)
			assert.ErrorIs(t, err, tt.expected.Error)
		})
	}
}

func TestParseWithPrefix_map_matches_process(t *testing.T) {
	type Envs struct {
		RedisURI string `env:"REDIS_URI"`
	}

	values := map[string]string{
		"FOO_REDIS_URI": "redis://redis:6379/prefixed",
		"REDIS_URI":     "redis://redis:6379/unprefixed",
	}

	for key, value := range values {
		t.Setenv(key, value)
	}

	fromMap, err := envs.ParseWithPrefix[Envs](envs.Map(values), "FOO_")
	require.NoError(t, err)

	fromProcess, err := envs.ParseWithPrefix[Envs](envs.OS(), "FOO_")
	require.NoError(t, err)

	assert.Equal(t, "redis://redis:6379/prefixed", fromMap.RedisURI)
	assert.Equal(t, fromProcess, fromMap)
}

func TestParse_with_default(t *testing.T) {
	t.Parallel()

	type Envs struct {
		RedisURI string `env:"REDIS_URI,default=redis://redis:6379/default"`
		MongoURI string `env:"MONGO_URI,default=mongodb://mongo:27017/default"`
	}

	type Expected struct {
		Envs  *Envs
		Error error
	}

	tests := []struct {
		description string
		values      map[string]string
		expected    Expected
	}{
		{
			description: "parse envs",
			values: map[string]string{
				"REDIS_URI": "redis://redis:6379/test",
				"MONGO_URI": "mongodb://mongo:27017/test",
			},
			expected: Expected{
				Envs: &Envs{
					RedisURI: "redis://redis:6379/test",
					MongoURI: "mongodb://mongo:27017/test",
				},
				Error: nil,
			},
		},
		{
			description: "parse envs with one set and one default",
			values: map[string]string{
				"REDIS_URI": "redis://redis:6379/test",
			},
			expected: Expected{
				Envs: &Envs{
					RedisURI: "redis://redis:6379/test",
					MongoURI: "mongodb://mongo:27017/default",
				},
				Error: nil,
			},
		},
		{
			description: "parse envs with all default",
			values:      map[string]string{},
			expected: Expected{
				Envs: &Envs{
					RedisURI: "redis://redis:6379/default",
					MongoURI: "mongodb://mongo:27017/default",
				},
				Error: nil,
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.description, func(t *testing.T) {
			t.Parallel()

			result, err := envs.Parse[Envs](envs.Map(tt.values))
			assert.Equal(t, tt.expected.Envs, result)
			assert.ErrorIs(t, err, tt.expected.Error)
		})
	}
}

func TestParse_with_required(t *testing.T) {
	t.Parallel()

	type Envs struct {
		RedisURI string `env:"REDIS_URI,required"`
		MongoURI string `env:"MONGO_URI,required"`
	}

	type Expected struct {
		Envs  *Envs
		Error error
	}

	tests := []struct {
		description string
		values      map[string]string
		expected    Expected
	}{
		{
			description: "parse envs",
			values: map[string]string{
				"REDIS_URI": "redis://redis:6379/test",
				"MONGO_URI": "mongodb://mongo:27017/test",
			},
			expected: Expected{
				Envs: &Envs{
					RedisURI: "redis://redis:6379/test",
					MongoURI: "mongodb://mongo:27017/test",
				},
				Error: nil,
			},
		},
		{
			description: "fail to parse envs when one env is missing",
			values: map[string]string{
				"REDIS_URI": "redis://redis:6379/test",
			},
			expected: Expected{
				Error: envs.ErrParse,
			},
		},
		{
			description: "fails to parse when all envs are missing",
			values:      map[string]string{},
			expected: Expected{
				Envs:  nil,
				Error: envs.ErrParse,
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.description, func(t *testing.T) {
			t.Parallel()

			result, err := envs.Parse[Envs](envs.Map(tt.values))
			assert.Equal(t, tt.expected.Envs, result)
			assert.ErrorIs(t, err, tt.expected.Error)
		})
	}
}