mirror of
https://github.com/halverneus/static-file-server.git
synced 2024-11-24 09:05:30 +00:00
Refactored and added unit tests for configuration
This commit is contained in:
parent
571765d935
commit
3700c31599
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
vendor/
|
||||
|
20
Dockerfile
20
Dockerfile
@ -1,7 +1,19 @@
|
||||
FROM golang:latest as builder
|
||||
COPY serve.go /
|
||||
WORKDIR /
|
||||
RUN CGO_ENABLED=0 go build -a -installsuffix cgo -o serve .
|
||||
FROM golang:1.10.3 as builder
|
||||
|
||||
ENV BUILD_DIR /go/src/github.com/halverneus/static-file-server
|
||||
ENV MAIN github.com/halverneus/static-file-server/bin/serve
|
||||
|
||||
RUN curl -fsSL -o /usr/local/bin/dep \
|
||||
https://github.com/golang/dep/releases/download/v0.4.1/dep-linux-amd64 && \
|
||||
chmod +x /usr/local/bin/dep
|
||||
|
||||
RUN mkdir -p ${BUILD_DIR}
|
||||
WORKDIR ${BUILD_DIR}
|
||||
COPY . .
|
||||
|
||||
RUN dep ensure -vendor-only
|
||||
RUN go test ./...
|
||||
RUN CGO_ENABLED=0 go build -a -installsuffix cgo -o /serve ${MAIN}
|
||||
|
||||
FROM scratch
|
||||
COPY --from=builder /serve /
|
||||
|
15
Gopkg.lock
generated
Normal file
15
Gopkg.lock
generated
Normal file
@ -0,0 +1,15 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/yaml.v2"
|
||||
packages = ["."]
|
||||
revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
|
||||
version = "v2.2.1"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "ce4cfa8aa3eb29f45e7ba341fdeac9820969e663181e81bddfc4a3aa2d5169bb"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
34
Gopkg.toml
Normal file
34
Gopkg.toml
Normal file
@ -0,0 +1,34 @@
|
||||
# Gopkg.toml example
|
||||
#
|
||||
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
||||
# for detailed Gopkg.toml documentation.
|
||||
#
|
||||
# required = ["github.com/user/thing/cmd/thing"]
|
||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project"
|
||||
# version = "1.0.0"
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project2"
|
||||
# branch = "dev"
|
||||
# source = "github.com/myfork/project2"
|
||||
#
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
#
|
||||
# [prune]
|
||||
# non-go = false
|
||||
# go-tests = true
|
||||
# unused-packages = true
|
||||
|
||||
|
||||
[[constraint]]
|
||||
name = "gopkg.in/yaml.v2"
|
||||
version = "2.2.1"
|
||||
|
||||
[prune]
|
||||
go-tests = true
|
||||
unused-packages = true
|
@ -6,10 +6,12 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/halverneus/static-file-server/config"
|
||||
)
|
||||
|
||||
var (
|
||||
version = "Version 1.1"
|
||||
version = "Version 1.3"
|
||||
|
||||
help = `
|
||||
NAME
|
||||
@ -126,17 +128,13 @@ func main() {
|
||||
}
|
||||
|
||||
// Collect environment variables.
|
||||
folder := env("FOLDER", "/web") + "/"
|
||||
host := env("HOST", "")
|
||||
port := env("PORT", "8080")
|
||||
showListing := envAsBool("SHOW_LISTING", true)
|
||||
tlsCert := env("TLS_CERT", "")
|
||||
tlsKey := env("TLS_KEY", "")
|
||||
urlPrefix := env("URL_PREFIX", "")
|
||||
if err := config.Load(""); nil != err {
|
||||
log.Fatalf("While loading configuration got %v", err)
|
||||
}
|
||||
|
||||
// If HTTPS is to be used, verify both TLS_* environment variables are set.
|
||||
if 0 < len(tlsCert) || 0 < len(tlsKey) {
|
||||
if 0 == len(tlsCert) || 0 == len(tlsKey) {
|
||||
if 0 < len(config.Get.TLSCert) || 0 < len(config.Get.TLSKey) {
|
||||
if 0 == len(config.Get.TLSCert) || 0 == len(config.Get.TLSKey) {
|
||||
log.Fatalln(
|
||||
"If value for environment variable 'TLS_CERT' or 'TLS_KEY' is set " +
|
||||
"then value for environment variable 'TLS_KEY' or 'TLS_CERT' must " +
|
||||
@ -146,8 +144,8 @@ func main() {
|
||||
}
|
||||
|
||||
// If the URL path prefix is to be used, verify it is properly formatted.
|
||||
if 0 < len(urlPrefix) &&
|
||||
(!strings.HasPrefix(urlPrefix, "/") || strings.HasSuffix(urlPrefix, "/")) {
|
||||
if 0 < len(config.Get.URLPrefix) &&
|
||||
(!strings.HasPrefix(config.Get.URLPrefix, "/") || strings.HasSuffix(config.Get.URLPrefix, "/")) {
|
||||
log.Fatalln(
|
||||
"Value for environment variable 'URL_PREFIX' must start " +
|
||||
"with '/' and not end with '/'. Example: '/my/prefix'",
|
||||
@ -156,18 +154,24 @@ func main() {
|
||||
|
||||
// Choose and set the appropriate, optimized static file serving function.
|
||||
var handler http.HandlerFunc
|
||||
if 0 == len(urlPrefix) {
|
||||
handler = handleListing(showListing, basicHandler(folder))
|
||||
if 0 == len(config.Get.URLPrefix) {
|
||||
handler = handleListing(config.Get.ShowListing, basicHandler(config.Get.Folder))
|
||||
} else {
|
||||
handler = handleListing(showListing, prefixHandler(folder, urlPrefix))
|
||||
handler = handleListing(config.Get.ShowListing, prefixHandler(config.Get.Folder, config.Get.URLPrefix))
|
||||
}
|
||||
http.HandleFunc("/", handler)
|
||||
|
||||
// Serve files over HTTP or HTTPS based on paths to TLS files being provided.
|
||||
if 0 == len(tlsCert) {
|
||||
log.Fatalln(http.ListenAndServe(host+":"+port, nil))
|
||||
binding := fmt.Sprintf("%s:%d", config.Get.Host, config.Get.Port)
|
||||
if 0 == len(config.Get.TLSCert) {
|
||||
log.Fatalln(http.ListenAndServe(binding, nil))
|
||||
} else {
|
||||
log.Fatalln(http.ListenAndServeTLS(host+":"+port, tlsCert, tlsKey, nil))
|
||||
log.Fatalln(http.ListenAndServeTLS(
|
||||
binding,
|
||||
config.Get.TLSCert,
|
||||
config.Get.TLSKey,
|
||||
nil,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
164
config/config.go
Normal file
164
config/config.go
Normal file
@ -0,0 +1,164 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
var (
|
||||
// Get the desired configuration value.
|
||||
Get struct {
|
||||
Folder string `yaml:"folder"`
|
||||
Host string `yaml:"host"`
|
||||
Port uint16 `yaml:"port"`
|
||||
ShowListing bool `yaml:"show-listing"`
|
||||
TLSCert string `yaml:"tls-cert"`
|
||||
TLSKey string `yaml:"tls-key"`
|
||||
URLPrefix string `yaml:"url-prefix"`
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
folderKey = "FOLDER"
|
||||
hostKey = "HOST"
|
||||
portKey = "PORT"
|
||||
showListingKey = "SHOW_LISTING"
|
||||
tlsCertKey = "TLS_CERT"
|
||||
tlsKeyKey = "TLS_KEY"
|
||||
urlPrefixKey = "URL_PREFIX"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultFolder = "/web"
|
||||
defaultHost = ""
|
||||
defaultPort = uint16(8080)
|
||||
defaultShowListing = true
|
||||
defaultTLSCert = ""
|
||||
defaultTLSKey = ""
|
||||
defaultURLPrefix = ""
|
||||
)
|
||||
|
||||
func init() {
|
||||
// init calls setDefaults to better support testing.
|
||||
setDefaults()
|
||||
}
|
||||
|
||||
func setDefaults() {
|
||||
Get.Folder = defaultFolder
|
||||
Get.Host = defaultHost
|
||||
Get.Port = defaultPort
|
||||
Get.ShowListing = defaultShowListing
|
||||
Get.TLSCert = defaultTLSCert
|
||||
Get.TLSKey = defaultTLSKey
|
||||
Get.URLPrefix = defaultURLPrefix
|
||||
}
|
||||
|
||||
// Load the configuration file.
|
||||
func Load(filename string) (err error) {
|
||||
// If no filename provided, assign envvars.
|
||||
if "" == filename {
|
||||
overrideWithEnvVars()
|
||||
return
|
||||
}
|
||||
|
||||
// Read contents from configuration file.
|
||||
var contents []byte
|
||||
if contents, err = ioutil.ReadFile(filename); nil != err {
|
||||
return
|
||||
}
|
||||
|
||||
// Parse contents into 'Get' configuration.
|
||||
if err = yaml.Unmarshal(contents, &Get); nil != err {
|
||||
return
|
||||
}
|
||||
overrideWithEnvVars()
|
||||
return
|
||||
}
|
||||
|
||||
// overrideWithEnvVars the default values and the configuration file values.
|
||||
func overrideWithEnvVars() {
|
||||
// Assign envvars, if set.
|
||||
Get.Folder = envAsStr(folderKey, Get.Folder)
|
||||
Get.Host = envAsStr(hostKey, Get.Host)
|
||||
Get.Port = envAsUint16(portKey, Get.Port)
|
||||
Get.ShowListing = envAsBool(showListingKey, Get.ShowListing)
|
||||
Get.TLSCert = envAsStr(tlsCertKey, Get.TLSCert)
|
||||
Get.TLSKey = envAsStr(tlsKeyKey, Get.TLSKey)
|
||||
Get.URLPrefix = envAsStr(urlPrefixKey, Get.URLPrefix)
|
||||
}
|
||||
|
||||
// envAsStr returns the value of the environment variable as a string if set.
|
||||
func envAsStr(key, fallback string) string {
|
||||
if value := os.Getenv(key); "" != value {
|
||||
return value
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
|
||||
// envAsUint16 returns the value of the environment variable as a uint16 if set.
|
||||
func envAsUint16(key string, fallback uint16) uint16 {
|
||||
// Retrieve the string value of the environment variable. If not set,
|
||||
// fallback is used.
|
||||
valueStr := os.Getenv(key)
|
||||
if "" == valueStr {
|
||||
return fallback
|
||||
}
|
||||
|
||||
// Parse the string into a uint16.
|
||||
base := 10
|
||||
bitSize := 16
|
||||
valueAsUint64, err := strconv.ParseUint(valueStr, base, bitSize)
|
||||
if nil != err {
|
||||
log.Printf(
|
||||
"Invalid value for '%s': %v\nUsing fallback: %d",
|
||||
key, err, fallback,
|
||||
)
|
||||
return fallback
|
||||
}
|
||||
return uint16(valueAsUint64)
|
||||
}
|
||||
|
||||
// envAsBool returns the value for an environment variable or, if not set, a
|
||||
// fallback value as a boolean.
|
||||
func envAsBool(key string, fallback bool) bool {
|
||||
// Retrieve the string value of the environment variable. If not set,
|
||||
// fallback is used.
|
||||
valueStr := os.Getenv(key)
|
||||
if "" == valueStr {
|
||||
return fallback
|
||||
}
|
||||
|
||||
// Parse the string into a boolean.
|
||||
value, err := strAsBool(valueStr)
|
||||
if nil != err {
|
||||
log.Printf(
|
||||
"Invalid value for '%s': %v\nUsing fallback: %t",
|
||||
key, err, fallback,
|
||||
)
|
||||
return fallback
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
// strAsBool converts the intent of the passed value into a boolean
|
||||
// representation.
|
||||
func strAsBool(value string) (result bool, err error) {
|
||||
lvalue := strings.ToLower(value)
|
||||
switch lvalue {
|
||||
case "0", "false", "f", "no", "n":
|
||||
result = false
|
||||
case "1", "true", "t", "yes", "y":
|
||||
result = true
|
||||
default:
|
||||
result = false
|
||||
msg := "Unknown conversion from string to bool for value '%s'"
|
||||
err = fmt.Errorf(msg, value)
|
||||
}
|
||||
return
|
||||
}
|
312
config/config_test.go
Normal file
312
config/config_test.go
Normal file
@ -0,0 +1,312 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
// Verify envvars are set.
|
||||
testFolder := "/my/directory"
|
||||
os.Setenv(folderKey, testFolder)
|
||||
if err := Load(""); nil != err {
|
||||
t.Errorf(
|
||||
"While loading an empty file name expected no error but got %v",
|
||||
err,
|
||||
)
|
||||
}
|
||||
if Get.Folder != testFolder {
|
||||
t.Errorf(
|
||||
"While loading an empty file name expected folder %s but got %s",
|
||||
testFolder, Get.Folder,
|
||||
)
|
||||
}
|
||||
|
||||
// Verify error if file doesn't exist.
|
||||
if err := Load("/this/file/should/never/exist"); nil == err {
|
||||
t.Error("While loading non-existing file expected error but got nil")
|
||||
}
|
||||
|
||||
// Verify bad YAML returns an error.
|
||||
func(t *testing.T) {
|
||||
filename := "testing.tmp"
|
||||
contents := []byte("{")
|
||||
defer os.Remove(filename)
|
||||
|
||||
if err := ioutil.WriteFile(filename, contents, 0666); nil != err {
|
||||
t.Errorf("Failed to save bad YAML file with: %v\n", err)
|
||||
}
|
||||
if err := Load(filename); nil == err {
|
||||
t.Error("While loading bad YAML expected error but got nil")
|
||||
}
|
||||
}(t)
|
||||
|
||||
// Verify good YAML returns no error and sets value.
|
||||
func(t *testing.T) {
|
||||
filename := "testing.tmp"
|
||||
testFolder := "/test/folder"
|
||||
contents := []byte(fmt.Sprintf(
|
||||
`{"folder": "%s"}`, testFolder,
|
||||
))
|
||||
defer os.Remove(filename)
|
||||
|
||||
if err := ioutil.WriteFile(filename, contents, 0666); nil != err {
|
||||
t.Errorf("Failed to save good YAML file with: %v\n", err)
|
||||
}
|
||||
if err := Load(filename); nil != err {
|
||||
t.Errorf(
|
||||
"While loading good YAML expected nil but got %v",
|
||||
err,
|
||||
)
|
||||
}
|
||||
}(t)
|
||||
}
|
||||
|
||||
func TestOverrideWithEnvvars(t *testing.T) {
|
||||
// Choose values that are different than defaults.
|
||||
testFolder := "/my/directory"
|
||||
testHost := "apets.life"
|
||||
testPort := uint16(666)
|
||||
testShowListing := false
|
||||
testTLSCert := "my.pem"
|
||||
testTLSKey := "my.key"
|
||||
testURLPrefix := "/url/prefix"
|
||||
|
||||
// Set all environment variables with test values.
|
||||
os.Setenv(folderKey, testFolder)
|
||||
os.Setenv(hostKey, testHost)
|
||||
os.Setenv(portKey, strconv.Itoa(int(testPort)))
|
||||
os.Setenv(showListingKey, fmt.Sprintf("%t", testShowListing))
|
||||
os.Setenv(tlsCertKey, testTLSCert)
|
||||
os.Setenv(tlsKeyKey, testTLSKey)
|
||||
os.Setenv(urlPrefixKey, testURLPrefix)
|
||||
|
||||
// Verification functions.
|
||||
equalStrings := func(t *testing.T, name, key, expected, result string) {
|
||||
if expected != result {
|
||||
t.Errorf(
|
||||
"While checking %s for '%s' expected '%s' but got '%s'",
|
||||
name, key, expected, result,
|
||||
)
|
||||
}
|
||||
}
|
||||
equalUint16 := func(t *testing.T, name, key string, expected, result uint16) {
|
||||
if expected != result {
|
||||
t.Errorf(
|
||||
"While checking %s for '%s' expected %d but got %d",
|
||||
name, key, expected, result,
|
||||
)
|
||||
}
|
||||
}
|
||||
equalBool := func(t *testing.T, name, key string, expected, result bool) {
|
||||
if expected != result {
|
||||
t.Errorf(
|
||||
"While checking %s for '%s' expected %t but got %t",
|
||||
name, key, expected, result,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Verify defaults.
|
||||
setDefaults()
|
||||
phase := "defaults"
|
||||
equalStrings(t, phase, folderKey, defaultFolder, Get.Folder)
|
||||
equalStrings(t, phase, hostKey, defaultHost, Get.Host)
|
||||
equalUint16(t, phase, portKey, defaultPort, Get.Port)
|
||||
equalBool(t, phase, showListingKey, defaultShowListing, Get.ShowListing)
|
||||
equalStrings(t, phase, tlsCertKey, defaultTLSCert, Get.TLSCert)
|
||||
equalStrings(t, phase, tlsKeyKey, defaultTLSKey, Get.TLSKey)
|
||||
equalStrings(t, phase, urlPrefixKey, defaultURLPrefix, Get.URLPrefix)
|
||||
|
||||
// Apply overrides.
|
||||
overrideWithEnvVars()
|
||||
|
||||
// Verify overrides.
|
||||
phase = "overrides"
|
||||
equalStrings(t, phase, folderKey, testFolder, Get.Folder)
|
||||
equalStrings(t, phase, hostKey, testHost, Get.Host)
|
||||
equalUint16(t, phase, portKey, testPort, Get.Port)
|
||||
equalBool(t, phase, showListingKey, testShowListing, Get.ShowListing)
|
||||
equalStrings(t, phase, tlsCertKey, testTLSCert, Get.TLSCert)
|
||||
equalStrings(t, phase, tlsKeyKey, testTLSKey, Get.TLSKey)
|
||||
equalStrings(t, phase, urlPrefixKey, testURLPrefix, Get.URLPrefix)
|
||||
}
|
||||
|
||||
func TestEnvAsStr(t *testing.T) {
|
||||
sv := "STRING_VALUE"
|
||||
fv := "FLOAT_VALUE"
|
||||
iv := "INT_VALUE"
|
||||
bv := "BOOL_VALUE"
|
||||
ev := "EMPTY_VALUE"
|
||||
uv := "UNSET_VALUE"
|
||||
|
||||
sr := "String Cheese" // String result
|
||||
fr := "123.456" // Float result
|
||||
ir := "-123" // Int result
|
||||
br := "true" // Bool result
|
||||
er := "" // Empty result
|
||||
fbr := "fallback result" // Fallback result
|
||||
efbr := "" // Empty fallback result
|
||||
|
||||
os.Setenv(sv, sr)
|
||||
os.Setenv(fv, fr)
|
||||
os.Setenv(iv, ir)
|
||||
os.Setenv(bv, br)
|
||||
os.Setenv(ev, er)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
key string
|
||||
fallback string
|
||||
result string
|
||||
}{
|
||||
{"Good string", sv, fbr, sr},
|
||||
{"Float string", fv, fbr, fr},
|
||||
{"Int string", iv, fbr, ir},
|
||||
{"Bool string", bv, fbr, br},
|
||||
{"Empty string", ev, fbr, fbr},
|
||||
{"Unset", uv, fbr, fbr},
|
||||
{"Good string with empty fallback", sv, efbr, sr},
|
||||
{"Unset with empty fallback", uv, efbr, efbr},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result := envAsStr(tc.key, tc.fallback)
|
||||
if tc.result != result {
|
||||
t.Errorf(
|
||||
"For %s with a '%s' fallback expected '%s' but got '%s'",
|
||||
tc.key, tc.fallback, tc.result, result,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnvAsUint16(t *testing.T) {
|
||||
ubv := "UPPER_BOUNDS_VALUE"
|
||||
lbv := "LOWER_BOUNDS_VALUE"
|
||||
hv := "HIGH_VALUE"
|
||||
lv := "LOW_VALUE"
|
||||
bv := "BOOL_VALUE"
|
||||
sv := "STRING_VALUE"
|
||||
uv := "UNSET_VALUE"
|
||||
|
||||
fbr := uint16(666) // Fallback result
|
||||
ubr := uint16(65535) // Upper bounds result
|
||||
lbr := uint16(0) // Lower bounds result
|
||||
|
||||
os.Setenv(ubv, "65535")
|
||||
os.Setenv(lbv, "0")
|
||||
os.Setenv(hv, "65536")
|
||||
os.Setenv(lv, "-1")
|
||||
os.Setenv(bv, "true")
|
||||
os.Setenv(sv, "Cheese")
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
key string
|
||||
fallback uint16
|
||||
result uint16
|
||||
}{
|
||||
{"Upper bounds", ubv, fbr, ubr},
|
||||
{"Lower bounds", lbv, fbr, lbr},
|
||||
{"Out-of-bounds high", hv, fbr, fbr},
|
||||
{"Out-of-bounds low", lv, fbr, fbr},
|
||||
{"Boolean", bv, fbr, fbr},
|
||||
{"String", sv, fbr, fbr},
|
||||
{"Unset", uv, fbr, fbr},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result := envAsUint16(tc.key, tc.fallback)
|
||||
if tc.result != result {
|
||||
t.Errorf(
|
||||
"For %s with a %d fallback expected %d but got %d",
|
||||
tc.key, tc.fallback, tc.result, result,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnvAsBool(t *testing.T) {
|
||||
tv := "TRUE_VALUE"
|
||||
fv := "FALSE_VALUE"
|
||||
bv := "BAD_VALUE"
|
||||
uv := "UNSET_VALUE"
|
||||
|
||||
os.Setenv(tv, "True")
|
||||
os.Setenv(fv, "NO")
|
||||
os.Setenv(bv, "BAD")
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
key string
|
||||
fallback bool
|
||||
result bool
|
||||
}{
|
||||
{"True with true fallback", tv, true, true},
|
||||
{"True with false fallback", tv, false, true},
|
||||
{"False with true fallback", fv, true, false},
|
||||
{"False with false fallback", fv, false, false},
|
||||
{"Bad with true fallback", bv, true, true},
|
||||
{"Bad with false fallback", bv, false, false},
|
||||
{"Unset with true fallback", uv, true, true},
|
||||
{"Unset with false fallback", uv, false, false},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result := envAsBool(tc.key, tc.fallback)
|
||||
if tc.result != result {
|
||||
t.Errorf(
|
||||
"For %s with a %t fallback expected %t but got %t",
|
||||
tc.key, tc.fallback, tc.result, result,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStrAsBool(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
value string
|
||||
result bool
|
||||
isError bool
|
||||
}{
|
||||
{"Empty value", "", false, true},
|
||||
{"False value", "0", false, false},
|
||||
{"True value", "1", true, false},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result, err := strAsBool(tc.value)
|
||||
if result != tc.result {
|
||||
t.Errorf(
|
||||
"Expected %t for %s but got %t",
|
||||
tc.result, tc.value, result,
|
||||
)
|
||||
}
|
||||
if tc.isError && nil == err {
|
||||
t.Errorf(
|
||||
"Expected error for %s but got no error",
|
||||
tc.value,
|
||||
)
|
||||
}
|
||||
if !tc.isError && nil != err {
|
||||
t.Errorf(
|
||||
"Expected no error for %s but got %v",
|
||||
tc.value, err,
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user