diff --git a/.gitignore b/.gitignore index cf6be149..e948fb75 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,5 @@ bin/ dist/ coverage/ .DS_Store -tests-report.json \ No newline at end of file +tests-report.json +README_doc.md \ No newline at end of file diff --git a/Makefile b/Makefile index 43caf79e..f9fa780b 100644 --- a/Makefile +++ b/Makefile @@ -54,6 +54,11 @@ update-readme-cover: prepare-cover-report $(COMPOSE_TOOLS_CMD_UP) update-readme-coverage update-readme-coverage .PHONY: update-readme-cover +## Update readme doc. +update-readme-doc: + $(COMPOSE_TOOLS_CMD_UP) update-readme-doc update-readme-doc +.PHONY: update-readme-doc + ## Run tests. test: $(COMPOSE_TOOLS_CMD_UP) run-tests run-tests diff --git a/README.md b/README.md index 079a90c6..26e48183 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,6 @@ Package getenv provides functionality for loading environment variables and parse them into go builtin types. Types supported: - -```text - string - []string - int @@ -24,6 +22,7 @@ Types supported: - []int32 - int64 - []int64 +- uint8 - uint64 - []uint64 - uint @@ -37,7 +36,6 @@ Types supported: - []time.Time - time.Duration - bool -``` ## Examples @@ -119,7 +117,7 @@ func main() { ``` - Output: +Output: ``` [string]: golly diff --git a/deployments/docker-compose/go-tools-docker-compose.yml b/deployments/docker-compose/go-tools-docker-compose.yml index 6285f85c..fc75ce62 100755 --- a/deployments/docker-compose/go-tools-docker-compose.yml +++ b/deployments/docker-compose/go-tools-docker-compose.yml @@ -37,6 +37,11 @@ services: service: tools entrypoint: /bin/sh -c './scripts/update-readme-coverage.sh' + update-readme-doc: + extends: + service: tools + entrypoint: /bin/sh -c './scripts/update-readme-doc.sh' + lint-full: extends: service: tools diff --git a/getenv.go b/getenv.go index ebd24395..0e307dc8 100644 --- a/getenv.go +++ b/getenv.go @@ -13,6 +13,7 @@ // - []int32 // - int64 // - []int64 +// - uint8 // - uint64 // - []uint64 // - uint diff --git a/getenv_test.go b/getenv_test.go index ab96753e..71eb3a62 100644 --- a/getenv_test.go +++ b/getenv_test.go @@ -1358,6 +1358,82 @@ func TestDurationOrDefault(t *testing.T) { } } +func TestUint8OrDefault(t *testing.T) { + type args struct { + key string + defaultVal uint8 + } + + type expected struct { + val uint8 + } + + var tests = []struct { + name string + precond precondition + args args + expected expected + }{ + { + name: "env not set - default returned", + precond: precondition{ + setenv: setenv{ + isSet: false, + val: "12", + }, + }, + args: args{ + key: testEnvKey, + defaultVal: 99, + }, + expected: expected{ + val: 99, + }, + }, + { + name: "env set - env value returned", + precond: precondition{ + setenv: setenv{ + isSet: true, + val: "12", + }, + }, + args: args{ + key: testEnvKey, + defaultVal: 99, + }, + expected: expected{ + val: 12, + }, + }, + { + name: "empty env value set - default returned", + precond: precondition{ + setenv: setenv{ + isSet: true, + val: "", + }, + }, + args: args{ + key: testEnvKey, + defaultVal: 99, + }, + expected: expected{ + val: 99, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.precond.maybeSetEnv(t, tt.args.key) + + got := getenv.EnvOrDefault(tt.args.key, tt.args.defaultVal) + assert.Equal(t, tt.expected.val, got) + }) + } +} + func TestUint64OrDefault(t *testing.T) { type args struct { key string diff --git a/internal/constraint.go b/internal/constraint.go index 58d9d066..587495cd 100644 --- a/internal/constraint.go +++ b/internal/constraint.go @@ -22,7 +22,7 @@ type ( // Uint is a constraint for unsigned integer and slice of unsigned integers. Uint interface { - uint64 | []uint64 | uint | []uint | []uint32 | uint32 + uint | []uint | uint8 | uint32 | []uint32 | uint64 | []uint64 } // Float is a constraint for floats and slice of floats. diff --git a/internal/iface.go b/internal/iface.go index 3ba8938e..0afe7cf7 100644 --- a/internal/iface.go +++ b/internal/iface.go @@ -15,7 +15,7 @@ func NewEnvParser(v any) EnvParser { p = newStringParser(t) case int, []int, int8, []int8, int16, []int16, int32, []int32, int64, []int64: p = newIntParser(t) - case uint64, []uint64, uint, []uint, uint32, []uint32: + case uint, []uint, uint8, uint32, []uint32, uint64, []uint64: p = newUintParser(t) case bool: p = boolParser(t) @@ -78,18 +78,20 @@ func newIntParser(v any) EnvParser { func newUintParser(v any) EnvParser { switch t := v.(type) { - case uint64: - return uint64Parser(t) - case []uint64: - return uint64SliceParser(t) + case uint8: + return uint8Parser(t) case uint: return uintParser(t) case []uint: return uintSliceParser(t) - case []uint32: - return uint32SliceParser(t) case uint32: return uint32Parser(t) + case []uint32: + return uint32SliceParser(t) + case uint64: + return uint64Parser(t) + case []uint64: + return uint64SliceParser(t) default: return nil } @@ -302,6 +304,14 @@ func (i uint64SliceParser) ParseEnv(key string, defaltVal any, options Parameter return val } +type uint8Parser uint + +func (d uint8Parser) ParseEnv(key string, defaltVal any, _ Parameters) any { + val := uint8OrDefault(key, defaltVal.(uint8)) + + return val +} + type uintParser uint func (d uintParser) ParseEnv(key string, defaltVal any, _ Parameters) any { diff --git a/internal/iface_test.go b/internal/iface_test.go index 396816a4..0b2f8bc3 100644 --- a/internal/iface_test.go +++ b/internal/iface_test.go @@ -7,6 +7,10 @@ import ( "github.com/stretchr/testify/assert" ) +type notsupported struct { + name string +} + func TestNewEnvParser(t *testing.T) { type args struct { v any @@ -83,7 +87,15 @@ func TestNewEnvParser(t *testing.T) { wantPanic: assert.NotPanics, }, { - name: "uint23", + name: "uint8", + args: args{ + v: uint8(1), + }, + want: uint8Parser(1), + wantPanic: assert.NotPanics, + }, + { + name: "uint32", args: args{ v: uint32(1), }, @@ -221,7 +233,9 @@ func TestNewEnvParser(t *testing.T) { { name: "not supported - panics", args: args{ - v: byte(1), + v: notsupported{ + name: "name", + }, }, want: nil, wantPanic: assert.Panics, @@ -359,6 +373,25 @@ func Test_ParseEnv(t *testing.T) { }, want: []float64{-1.2, 0.2}, }, + { + name: "uint8Parser", + s: uint8Parser(0), + precond: precondition{ + setenv: setenv{ + isSet: true, + val: "12", + }, + }, + args: args{ + key: testEnvKey, + defaltVal: uint8(99), + in2: Parameters{ + Separator: ",", + Layout: "", + }, + }, + want: uint8(12), + }, { name: "uint64Parser", s: uint64Parser(0), diff --git a/internal/parsers.go b/internal/parsers.go index a85ac4a1..fa1d662b 100644 --- a/internal/parsers.go +++ b/internal/parsers.go @@ -470,7 +470,29 @@ func uint64SliceOrDefault(key string, defaultVal []uint64, sep string) []uint64 return val } -// uintOrDefault retrieves the unt64 value of the environment variable named +// uint8OrDefault retrieves the unt8 value of the environment variable named +// by the key. +// If variable not set or value is empty - defaultVal will be returned. +func uint8OrDefault(key string, defaultVal uint8) uint8 { + env := stringOrDefault(key, "") + if env == "" { + return defaultVal + } + + const ( + base = 10 + bitsize = 8 + ) + + val, err := strconv.ParseUint(env, base, bitsize) + if err != nil { + return defaultVal + } + + return uint8(val) +} + +// uintOrDefault retrieves the unt value of the environment variable named // by the key. // If variable not set or value is empty - defaultVal will be returned. func uintOrDefault(key string, defaultVal uint) uint { diff --git a/internal/parsers_test.go b/internal/parsers_test.go index aeecde17..a97db321 100644 --- a/internal/parsers_test.go +++ b/internal/parsers_test.go @@ -2070,6 +2070,98 @@ func Test_uint64SliceOrDefault(t *testing.T) { } } +func Test_uint8OrDefault(t *testing.T) { + type args struct { + key string + defaultVal uint8 + } + + type expected struct { + val uint8 + } + + var tests = []struct { + name string + precond precondition + args args + expected expected + }{ + { + name: "env not set - default returned", + precond: precondition{ + setenv: setenv{ + isSet: false, + val: "12", + }, + }, + args: args{ + key: testEnvKey, + defaultVal: 99, + }, + expected: expected{ + val: 99, + }, + }, + { + name: "env set - env value returned", + precond: precondition{ + setenv: setenv{ + isSet: true, + val: "12", + }, + }, + args: args{ + key: testEnvKey, + defaultVal: 99, + }, + expected: expected{ + val: 12, + }, + }, + { + name: "empty env value set - default returned", + precond: precondition{ + setenv: setenv{ + isSet: true, + val: "", + }, + }, + args: args{ + key: testEnvKey, + defaultVal: 99, + }, + expected: expected{ + val: 99, + }, + }, + { + name: "malformed env value set - default returned", + precond: precondition{ + setenv: setenv{ + isSet: true, + val: "iii99", + }, + }, + args: args{ + key: testEnvKey, + defaultVal: 99, + }, + expected: expected{ + val: 99, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.precond.maybeSetEnv(t, tt.args.key) + + got := uint8OrDefault(tt.args.key, tt.args.defaultVal) + assert.Equal(t, tt.expected.val, got) + }) + } +} + func Test_uintOrDefault(t *testing.T) { type args struct { key string diff --git a/scripts/update-readme-doc.sh b/scripts/update-readme-doc.sh new file mode 100755 index 00000000..cce0a1b7 --- /dev/null +++ b/scripts/update-readme-doc.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +set -Eeuo pipefail + +SCRIPT_NAME="$(basename "$0")" +SCRIPT_DIR="$(dirname "$0")" +REPO_ROOT="$(cd "${SCRIPT_DIR}" && git rev-parse --show-toplevel)" +SCRIPTS_DIR="${REPO_ROOT}/scripts" + +source "${SCRIPTS_DIR}/helpers-source.sh" + +echo "${SCRIPT_NAME} is running... " + +checkInstalled 'goreadme' + + +goreadme -credit=false -skip-sub-packages > README_doc.md + +echo "${SCRIPT_NAME} done."