♻️ Use uint8 for Env
This commit is contained in:
		
					parent
					
						
							
								d7de194a90
							
						
					
				
			
			
				commit
				
					
						917f919401
					
				
			
		
					 6 changed files with 135 additions and 21 deletions
				
			
		|  | @ -49,6 +49,7 @@ func getTomlFile() string { | ||||||
| 
 | 
 | ||||||
| var confStr = ` | var confStr = ` | ||||||
| base_url = "http://localhost:4523/" | base_url = "http://localhost:4523/" | ||||||
|  | env = "dev" | ||||||
| 
 | 
 | ||||||
| [stores] | [stores] | ||||||
| store = "sqlite" | store = "sqlite" | ||||||
|  |  | ||||||
|  | @ -13,7 +13,7 @@ func TestEnvDefaultsToDev(t *testing.T) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestInvalidEnvReturnsDev(t *testing.T) { | func TestInvalidEnvReturnsDev(t *testing.T) { | ||||||
| 	c := config{env: Env("foobar")} | 	c := config{env: Env(255)} | ||||||
| 	assert.Equal(t, Dev, c.Env()) | 	assert.Equal(t, Dev, c.Env()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,12 +1,20 @@ | ||||||
| package config | package config | ||||||
| 
 | 
 | ||||||
| type Env string | import ( | ||||||
|  | 	"errors" | ||||||
|  | 	"fmt" | ||||||
|  | 	"strings" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | //go:generate stringer -type Env | ||||||
|  | 
 | ||||||
|  | type Env uint8 | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
| 	Dev  Env = "dev" | 	Dev Env = iota + 1 | ||||||
| 	Prod Env = "prod" | 	Prod | ||||||
| 	Qa   Env = "qa" | 	Qa | ||||||
| 	Test Env = "test" | 	Test | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| var Envs = [...]Env{ | var Envs = [...]Env{ | ||||||
|  | @ -16,6 +24,28 @@ var Envs = [...]Env{ | ||||||
| 	Test, | 	Test, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (e Env) MarshalText() ([]byte, error) { | ||||||
|  | 	return []byte(e.String()), nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var ErrEnvUnmarshal = errors.New("unable to unmarshal value") | ||||||
|  | 
 | ||||||
|  | func (e *Env) UnmarshalText(text []byte) error { | ||||||
|  | 	if e == nil { | ||||||
|  | 		return fmt.Errorf("%w: nil pointer", ErrEnvUnmarshal) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	val := strings.ToUpper(string(text)) | ||||||
|  | 
 | ||||||
|  | 	for _, ee := range Envs { | ||||||
|  | 		if val == strings.ToUpper(ee.String()) { | ||||||
|  | 			*e = ee | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return fmt.Errorf("%w: invalid value: %s", ErrEnvUnmarshal, text) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func ValidEnvOrDev(e Env) Env { | func ValidEnvOrDev(e Env) Env { | ||||||
| 	if ValidEnv(e) { | 	if ValidEnv(e) { | ||||||
| 		return e | 		return e | ||||||
|  | @ -31,7 +61,3 @@ func ValidEnv(env Env) bool { | ||||||
| 	} | 	} | ||||||
| 	return false | 	return false | ||||||
| } | } | ||||||
| 
 |  | ||||||
| func (e Env) String() string { |  | ||||||
| 	return string(e) |  | ||||||
| } |  | ||||||
|  |  | ||||||
							
								
								
									
										27
									
								
								config/env_string.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								config/env_string.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | ||||||
|  | // Code generated by "stringer -type Env"; DO NOT EDIT. | ||||||
|  | 
 | ||||||
|  | package config | ||||||
|  | 
 | ||||||
|  | import "strconv" | ||||||
|  | 
 | ||||||
|  | func _() { | ||||||
|  | 	// An "invalid array index" compiler error signifies that the constant values have changed. | ||||||
|  | 	// Re-run the stringer command to generate them again. | ||||||
|  | 	var x [1]struct{} | ||||||
|  | 	_ = x[Dev-1] | ||||||
|  | 	_ = x[Prod-2] | ||||||
|  | 	_ = x[Qa-3] | ||||||
|  | 	_ = x[Test-4] | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const _Env_name = "DevProdQaTest" | ||||||
|  | 
 | ||||||
|  | var _Env_index = [...]uint8{0, 3, 7, 9, 13} | ||||||
|  | 
 | ||||||
|  | func (i Env) String() string { | ||||||
|  | 	i -= 1 | ||||||
|  | 	if i >= Env(len(_Env_index)-1) { | ||||||
|  | 		return "Env(" + strconv.FormatInt(int64(i+1), 10) + ")" | ||||||
|  | 	} | ||||||
|  | 	return _Env_name[_Env_index[i]:_Env_index[i+1]] | ||||||
|  | } | ||||||
|  | @ -1,21 +1,81 @@ | ||||||
| package config | package config | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"encoding" | ||||||
|  | 	"fmt" | ||||||
|  | 	"strings" | ||||||
| 	"testing" | 	"testing" | ||||||
| 
 | 
 | ||||||
| 	"github.com/stretchr/testify/assert" | 	"github.com/stretchr/testify/assert" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | var _ encoding.TextMarshaler = Env(0) | ||||||
|  | var _ encoding.TextUnmarshaler = new(Env) | ||||||
|  | var _ fmt.Stringer = Env(0) | ||||||
|  | 
 | ||||||
| func TestEnvString(t *testing.T) { | func TestEnvString(t *testing.T) { | ||||||
| 	cases := Envs[:] | 	testcases := []struct { | ||||||
| 	cases = append(cases, Env("foobar"), Env(""), Env("42"), Env("✨")) | 		expected string | ||||||
| 	for _, e := range cases { | 		val      Env | ||||||
| 		t.Run(string(e), func(t *testing.T) { | 	}{ | ||||||
| 			assert.Equal(t, string(e), e.String()) | 		{"Dev", Dev}, | ||||||
|  | 		{"Prod", Prod}, | ||||||
|  | 		{"Qa", Qa}, | ||||||
|  | 		{"Test", Test}, | ||||||
|  | 		{"Env(0)", Env(0)}, | ||||||
|  | 		{"Env(255)", Env(255)}, | ||||||
|  | 	} | ||||||
|  | 	for _, testcase := range testcases { | ||||||
|  | 		t.Run(testcase.expected, func(sub *testing.T) { | ||||||
|  | 			assert.Equal(t, testcase.expected, testcase.val.String()) | ||||||
|  | 			by, er := testcase.val.MarshalText() | ||||||
|  | 			assert.NoError(t, er) | ||||||
|  | 			assert.Equal(t, []byte(testcase.expected), by) | ||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type unmarshaltest struct { | ||||||
|  | 	name string | ||||||
|  | 	in   []byte | ||||||
|  | 	exp  Env | ||||||
|  | 	err  string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestEnvUnmarshalText(t *testing.T) { | ||||||
|  | 	testcases := []unmarshaltest{ | ||||||
|  | 		{"empty", []byte{}, Env(0), "invalid value: "}, | ||||||
|  | 		{"bad value", []byte("foobar"), Env(0), "invalid value: foobar"}, | ||||||
|  | 	} | ||||||
|  | 	for _, e := range Envs { | ||||||
|  | 		testcases = append(testcases, unmarshaltest{e.String() + "-lower", []byte(strings.ToLower(e.String())), e, ""}) | ||||||
|  | 		testcases = append(testcases, unmarshaltest{e.String() + "-upper", []byte(strings.ToUpper(e.String())), e, ""}) | ||||||
|  | 		testcases = append(testcases, unmarshaltest{e.String(), []byte(e.String()), e, ""}) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for _, testcase := range testcases { | ||||||
|  | 		t.Run(testcase.name, func(sub *testing.T) { | ||||||
|  | 			var e Env | ||||||
|  | 			er := (&e).UnmarshalText(testcase.in) | ||||||
|  | 			if testcase.err == "" { | ||||||
|  | 				assert.NoError(t, er) | ||||||
|  | 				assert.Equal(t, testcase.exp, e) | ||||||
|  | 			} else { | ||||||
|  | 				assert.Empty(t, e) | ||||||
|  | 				assert.ErrorContains(t, er, testcase.err) | ||||||
|  | 				assert.ErrorIs(t, er, ErrEnvUnmarshal) | ||||||
|  | 			} | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestEnvUnmarshalTextNil(t *testing.T) { | ||||||
|  | 	var e *Env | ||||||
|  | 	er := e.UnmarshalText([]byte("prod")) | ||||||
|  | 	assert.ErrorContains(t, er, "nil pointer") | ||||||
|  | 	assert.ErrorIs(t, er, ErrEnvUnmarshal) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func TestValidEnv(t *testing.T) { | func TestValidEnv(t *testing.T) { | ||||||
| 	cases := [...]struct { | 	cases := [...]struct { | ||||||
| 		e   Env | 		e   Env | ||||||
|  | @ -25,9 +85,8 @@ func TestValidEnv(t *testing.T) { | ||||||
| 		{Prod, true}, | 		{Prod, true}, | ||||||
| 		{Qa, true}, | 		{Qa, true}, | ||||||
| 		{Test, true}, | 		{Test, true}, | ||||||
| 		{Env("foobar"), false}, | 		{Env(0), false}, | ||||||
| 		{Env(""), false}, | 		{Env(255), false}, | ||||||
| 		{Env("✨"), false}, |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for _, c := range cases { | 	for _, c := range cases { | ||||||
|  | @ -46,9 +105,8 @@ func TestValidEnvOrDev(t *testing.T) { | ||||||
| 		{Prod, Prod}, | 		{Prod, Prod}, | ||||||
| 		{Qa, Qa}, | 		{Qa, Qa}, | ||||||
| 		{Test, Test}, | 		{Test, Test}, | ||||||
| 		{Env("foobar"), Dev}, | 		{Env(0), Dev}, | ||||||
| 		{Env(""), Dev}, | 		{Env(255), Dev}, | ||||||
| 		{Env("✨"), Dev}, |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for _, c := range cases { | 	for _, c := range cases { | ||||||
|  |  | ||||||
|  | @ -23,6 +23,7 @@ func TestLoadTomlGood(t *testing.T) { | ||||||
| 	defer os.Remove(tmp.Name()) | 	defer os.Remove(tmp.Name()) | ||||||
| 	defer tmp.Close() | 	defer tmp.Close() | ||||||
| 	fmt.Fprintln(tmp, `name = "Cool"`) | 	fmt.Fprintln(tmp, `name = "Cool"`) | ||||||
|  | 	fmt.Fprintln(tmp, `env = "prod"`) | ||||||
| 	fmt.Fprintln(tmp, "[stores]") | 	fmt.Fprintln(tmp, "[stores]") | ||||||
| 	fmt.Fprintln(tmp, `store = "sqlite"`) | 	fmt.Fprintln(tmp, `store = "sqlite"`) | ||||||
| 	fmt.Fprintln(tmp, "[stores.settings.sqlite]") | 	fmt.Fprintln(tmp, "[stores.settings.sqlite]") | ||||||
|  | @ -31,6 +32,7 @@ func TestLoadTomlGood(t *testing.T) { | ||||||
| 	c, e := LoadFromToml(tmp.Name()) | 	c, e := LoadFromToml(tmp.Name()) | ||||||
| 	assert.NoError(t, e) | 	assert.NoError(t, e) | ||||||
| 	assert.Equal(t, "Cool", c.Name()) | 	assert.Equal(t, "Cool", c.Name()) | ||||||
|  | 	assert.Equal(t, Prod, c.Env()) | ||||||
| 
 | 
 | ||||||
| 	st, err := c.Store("") | 	st, err := c.Store("") | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue